---
title: "Palumb vs Knock: notification workflows that stay in your own code"
url: "https://palumb.com/compare/knock"
description: "Knock bills a message per channel and hosts your workflows as JSON in the US. Palumb bills the run, keeps it in your repository, and runs in the EU."
---

# Palumb vs Knock: notification workflows that stay in your own code

Written in your own repository, rendered by your own template engine, delivered through your own provider. The delivery path is open source, and the service is operated in the European Union under EU law alone.

[Join the beta](/waitlist/) [Jump to the comparison](#comparison)

Free up to 500 runs a month, and the beta is that free plan, so there is nothing to expire.

## Notification orchestration you stay in control of

Knock: Richer workflow functions and an in-app feed. A New York company, and no self-hosting path at all.

Palumb executes the notification workflows you write, and takes nothing else. There is no builder to define them in, no template system to adopt and no sending pool to share: the workflow is a function in your repository, the message is whatever your own engine rendered, and it leaves on your own provider credentials. What Palumb runs is the part that is genuinely hard: resolving who should be told, executing steps durably across days and deploys, and keeping the record of every attempt.

Why teams pick Palumb

-   Workflows in your repository, not Palumb's
-   No lock-in: your template engine, your provider
-   Open source, and free to self-host
-   One EU jurisdiction, nothing to authorise

## What Knock asks you to accept

Every line comes from Knock's own documentation, checked on 25 August 2026.

### Your workflow becomes a JSON document

Branching is a conditions builder with nine condition types. In Palumb it is `if`, in your own language, with your own libraries. They also have an HTTP step for reaching your systems, configured “via a key-value editor”, and Palumb has no equivalent: a workflow decides and sends, and what happens in your system is your own handler reacting to the delivery.

### The release path is theirs

“A commit is not a save”: a change reaches production only once committed inside Knock and promoted. And “your Knock branches can mirror your Git branches”: two branch systems to keep in step. Your `git push` releases nothing.

### Nothing runs outside Knock

The product is closed and there is no self-hosted edition on any plan, Enterprise included. Templates are Liquid that “must belong to a single channel step”, and the workflow is JSON only their engine reads. The exit is a rewrite. Palumb's whole delivery path is AGPL-3.0.

### One message, per person, per channel

Their unit is “a message successfully sent to a single user on a single channel”, so a run that sends an email and an in-app notification bills twice. Palumb counts the run once, whatever it touches inside.

### You pay for a growth platform

Knock sells to engineering, growth and marketing operations, and two of its three billing meters exist for the second and third: guide active users and AI agent credits. If nobody at your company will touch those, the $250 covers them anyway.

### Processed in the United States

Their privacy policy: personal information “will be processed and stored in the US”. No region or residency option is named anywhere, so Knock is a US sub-processor on the list you publish to your own customers.

## Palumb runs the workflow, and touches nothing else

The parts it runs are the ones that are easy to promise and slow to get right: waits survive a deploy, retries do not hammer the provider, and every attempt leaves a record.

[The full list is here](/features/).

A workflow branching into the three ways time enters it, all three of them steps in its body: gathering events until Monday, a durable delay of three days, and waiting for a shipped signal.

### Gathering, waiting, or sleeping for days.

A run can gather what arrives **until an instant your code names**, stay alive through **hours or days** without losing its place across a crash or a deploy, or pause until **your app sends a signal** or the timeout fires.

### Any sending provider.

Send through the **channel a workflow needs** (**Email, SMS, Telegram, Slack or push**), each on your own sending provider, never pooled with anyone else's.

### Fan-out.

**Subscribe a recipient to a topic** once; every **trigger** on that topic reaches everyone still on it, each with their own run. No loop you write yourself.

### However you reach it.

Open the **dashboard** to look, call the **REST API** to build on it, or point your own **AI agent** at the MCP server. Same data, three ways in.

### Tried, tracked, never twice.

A failed send is retried **on a schedule that backs off**, a retry never duplicates one that already went out (it carries the same **Message-ID**), and **every attempt** ends up in the record: accepted, failed or bounced, with the reason.

Three events reach one POST /sendEvent: comment.added, task.assigned, deadline.soon. It collects them into a single digest document with three entries and one email.

### Digests.

**Each event becomes one item** in a digest that builds up over a window; when it closes, every item goes out in **one notification**, not one message per event.

Four template syntaxes stacked: a Handlebars tag, a React Email component, an MJML tag, and a plain template string.

### Any template engine.

**Keep the template engine you already use**: MJML, React Email, Handlebars, or a plain string. Palumb never renders; it only delivers what you hand it.

## Just write the workflow

A workflow is a function in your codebase. Our SDK gives it durable steps (a send, a wait on the clock, a pause until something happens in your product), and each one survives a crash and a deploy. There is nothing to define in a dashboard, and no copy of it on Palumb's side to drift from yours.

Three stacked boxes in one column, joined by a rail. Nothing travels along the rail. Instead the stretch of rail between two boxes fills, from the caller down to the one being called, holds while that one works, and then drains back the way it came. The fill is always the same grey, the ink of the Palumb mark: the line belongs to Palumb, and which end it starts from already says who placed the call.

At the top yourapp.com/backend, your own application, with the calls it makes into Palumb: trigger, for the orderPlaced workflow on topic.order-24, and days later sendEvent, for the order.shipped event. Each call is marked with a small square that fills in once Palumb has it, and appears only when it happens, so nothing is on screen before you make it, and the rail below it fills until Palumb holds the run, then drains back.

In the middle palumb itself, the durable engine, and it is the one box that is not an address because it is not something you run. It says one thing, running workflow, and it blinks, because a live run is the only thing in the figure that is happening rather than recorded. It appears only when the trigger arrives: before you call, there is nothing of yours in Palumb. Underneath it a row of small purple tokens grows, one for each step that has closed, each carrying that step's number, so by the end there are five and the row is the journal.

At the bottom yourapp.com/workflows/orderPlaced, your own workflow code, holding the program itself: the five steps numbered one to five: step.send for the confirmation, step.waitForEvent for the shipped signal with a thirty day limit, step.send for the tracking, step.delay of three days, and step.send for the feedback. Palumb calls down into it one step at a time, the rail filling down to that line and draining back. The moment a step is recorded its number leaves the line, replaced by a tick, and reappears as a token under Palumb: you wrote the step, we are the ones who remember it ran.

The steps are yours because they are written in your repository; what Palumb keeps is the place in the list. Through the thirty day wait and the three day delay the rail down to your code is grey and empty while the run stays alive in Palumb, which is why the run survives a wait in which your server does nothing at all.

order-placed.ts

```ts
workflow("orderPlaced", async ({ payload, step }) => {
  await step.send("confirmation", "email", () => confirmation(payload))

  const shipped = await step.waitForEvent("shipped", {
    event: "order.shipped",
    timeout: "30d",
  })
  if (!shipped) return

  await step.send("tracking", "email", () => tracking(shipped))

  await step.delay("cool-off", { seconds: 3 * 24 * 3600 })
  return step.send("feedback", "email", () => feedback(payload))
})
```

Worked examples, with the code

-   [How do you follow an order all the way to feedback?](/use-cases/order-updates/)
-   [How do you chase an unpaid invoice without chasing someone who paid?](/use-cases/unpaid-invoice/)
-   [How do you nudge a user who signed up and never came back?](/use-cases/activation-reminders/)
-   [How do you warn before a trial ends, and stop the moment they upgrade?](/use-cases/trial-ending/)
-   [How do you send a weekly summary on a fixed schedule?](/use-cases/weekly-summary/)
-   [How do you stop sending one email per comment?](/use-cases/comment-bursts/)

## Palumb vs Knock compared

Ownership, deployment, jurisdiction, pricing and what each of those means once you have signed.

|  | Knock | Palumb | What this means for you |
| --- | --- | --- | --- |
| Open source | No: proprietary, client SDKs aside | Yes: the whole delivery path, AGPL-3.0 | If the relationship ends you have something to run, not something to rebuild. |
| Deployment | Their cloud only, on every plan | Our cloud, or your own servers: three services | Lock-in is the design there, not an oversight. You can move where notifications run when compliance or procurement changes its mind. |
| What a workflow is | A JSON document stored in Knock | A function in your repository | Reviewed, typed and tested by the tools already running over the rest of your code. |
| Who can change a workflow | Anyone with a login, in the dashboard | Whoever can deploy your application | If someone outside engineering has to edit notifications, Knock is built for that and Palumb is not. |
| Templates | Liquid, and only inside a Knock workflow | Yours: MJML, React Email, a string | Nothing new to learn, and nothing to rewrite the day you leave. |
| Pricing metric | Messages sent, per user, per channel | Runs, per recipient | Their bill scales with channels and Palumb's does not: 25,000 runs on two channels is 50,000 messages there, and 25,000 runs with Palumb. |
| Plans | Free to 10,000 messages, then $250/mo | Free to 500 runs, then €19, €49, €149 | Under 10,000 messages their free plan covers what Palumb charges for. Over it, their next step is $250 and Palumb's is €49. |
| Where data is processed | United States | European Union (Scaleway, France) | You answer the residency question in your own vendor assessment without an exception. |
| Which law reaches the company | US law, incl. the CLOUD Act | EU law alone | No adequacy decision to depend on, and none to lose. |
| Delivery record kept for | 30 days; 90 on Enterprise | 90 days on every plan | A dispute eight weeks later is still answerable, on the free plan. |
| Environments | Unlimited on every plan | None | Dev, staging and production mean three accounts with Palumb. This row is theirs. |
| Certifications and SLA | SOC 2 Type 2, GDPR, CCPA, HIPAA; 99.9% | None | A buyer who wants an audit report on paper should buy Knock, and that is the right call. |
| Status | Generally available, with public customers | Private beta, no track record | You would be early, and being early carries a risk no argument removes. |

### Doesn't the United States have an EU adequacy decision?

It does, since 2023, and it still stands, so the transfer is lawful. It answers a different question from the one procurement asks: not which government can compel the company once the data is there. [The long version is on the jurisdiction page](/eu-jurisdiction/).

Taken from Knock's own [pricing page](https://knock.app/pricing), [privacy policy](https://knock.app/legal/privacy-policy) and [documentation](https://docs.knock.app/): data retention, version control, template editor, conditions, the [workflow functions](https://docs.knock.app/concepts/workflows) and the [CLI file structure](https://docs.knock.app/developer-tools/knock-cli). Checked on 25 August 2026. Facts about other companies go stale, and being corrected beats being wrong: if a fact here is out of date, [tell us](/contact/) and Palumb will fix it.

## Frequently asked questions

### What is the main difference between Palumb and Knock?

Palumb is open source, and it does one thing: it orchestrates. The workflow is a function in your own codebase, in your own language, deployed with the rest of your application; your template engine renders the message and your own provider sends it. Palumb resolves the recipients, executes the steps durably (waits included), and keeps the record of every attempt. You can also run the whole thing yourself, because the entire delivery path is AGPL-3.0 and self-hosting is free.

Knock is the opposite arrangement: proprietary software with no self-hosted edition on any plan, workflows stored as JSON in their system, templates in their own Liquid, and all of it running on their infrastructure in the United States. They bill a message per channel; Palumb bills the run. On breadth of product (in-app inbox, push, guides, certifications), Knock is ahead of Palumb and it is not close.

### Is Knock open source?

No. Knock is proprietary software. What they publish is the part that runs on your side (the client SDKs, the CLI, a React library, the docs), which every vendor in this category does because otherwise nobody would import them. The engine that stores your workflows and holds your data is closed, and there is no self-hosted edition on any plan, Enterprise included. Palumb publishes the whole delivery path under AGPL-3.0, and self-hosting is free.

### Can I keep my notification workflows in my own git with Knock?

You can keep a copy. `knock workflow pull` writes a `workflow.json`, and `push` sends it back, but their docs say “a commit is not a save”: nothing reaches a run triggered via the API until you commit it inside Knock and promote it. The release event is theirs, and the file only means something to their engine.

### How much does Knock cost after the free plan?

$250 a month. The free Developer plan covers 10,000 messages; the next plan up is $250 flat for 50,000, then $0.005 each. There is no plan in between. Palumb's steps above the free 500 runs are €19, €49 and €149. Both are each vendor's published prices, in their own currency.

### Does Knock bill per channel?

Yes. Their pricing page defines the unit as “a message successfully sent to a single user on a single channel” and gives the example itself: an in-app message plus an email for one user counts as two. Palumb counts the execution once per recipient, so adding a channel changes their bill and not Palumb's.

### Where does Knock store my data?

In the United States. Their privacy policy states that personal information “will be processed and stored in the US”, under Standard Contractual Clauses and the EU-U.S. Data Privacy Framework. No EU region or residency option is named in their documentation or on their security page. Palumb is operated in the European Union, on Scaleway in France.

## The other comparisons

Six of them, each conceding first. If you are drawing up a shortlist, these are the rest of it, and [the index compares all six side by side](/compare/).

-   [Palumb vs Novu](/compare/novu/)
    
    The other self-hostable one, and the closest thing we have to a mirror. Bigger product, EU regions, and a company outside the Union.
    
-   [Palumb vs Courier](/compare/courier/)
    
    More channels and real certifications. The only vendor here who publishes whose infrastructure runs its EU region, which is worth saying out loud.
    
-   [Palumb vs SuprSend](/compare/suprsend/)
    
    Multi-tenancy done properly, which is our own gap. Also a Delaware company processing data in the United States.
    
-   [Palumb vs MagicBell](/compare/magicbell/)
    
    An in-app inbox first, with a workflow engine of four commands and none of them waiting for an event. A San Francisco company that counts a delivery per channel.
    
-   [Palumb vs Building it yourself](/compare/build-it-yourself/)
    
    The competitor almost everyone actually picks, and for most teams the right answer. Here is where that stops being true.
    

Everyone who joins gets in, and it costs nothing. Your invite goes out when the beta opens.

[Join the beta](/waitlist/)