---
title: "Palumb vs MagicBell: notification workflows that stay in your own code"
url: "https://palumb.com/compare/magicbell"
description: "MagicBell is an in-app inbox whose workflow engine cannot wait for an event, and it bills one delivery per channel per user. Palumb counts the run once."
---

# Palumb vs MagicBell: 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

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 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 MagicBell asks you to accept

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

### Four commands, and none of them waits for an event

The whole engine is `broadcast`, `wait` for a fixed number of seconds, `pause` until something calls the API to resume it, and `abort` (their page, which adds “more commands coming soon”). Nothing waits for an event on its own. In Palumb that is a step with a timeout.

### A delivery per channel, with their own example

From their pricing FAQ: “if you send a notification to 100 users, all receive it in\_app, but only 50 receive an email; we count that as 150 deliveries”. Palumb counts the run once per recipient, whatever it touches inside, so adding a channel changes their bill and not Palumb's.

### A thousand deliveries free, then $249

The free plan is 1,000 deliveries a month and one project (an order of magnitude under the free tier at Knock or Courier), and the next step is $249 flat, with nothing in between and $99 for each project past five. Palumb's steps above 500 runs are €19, €49 and €149.

### MagicBell is proprietary

The client SDKs are on GitHub; the engine that runs your workflows and holds your data is closed, and there is no self-hosted edition on any plan. Their cloud is the only place it runs. Palumb's whole delivery path is AGPL-3.0 and self-hosting is free.

### JSON you can post is not code you own

Their workflows are JSON sent through the API, which is closer to code than a visual canvas: that is a genuine point in their favour. It is still their format, with their Liquid inside it, executed by their engine. A Palumb workflow is a function in your language, running in your deployment.

### The privacy policy does not say where the data is

MagicBell, Inc. is at 2261 Market Street, San Francisco. On the location of processing their policy says only that data is handled “at the Owner's operating offices and in any other places where the parties involved in the processing are located”: no country, no region, no residency option. Palumb: the European Union, on Scaleway in France.

## 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 MagicBell compared

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

|  | MagicBell | Palumb | What this means for you |
| --- | --- | --- | --- |
| Legal entity | MagicBell, Inc., San Francisco, California | One founder, Italy | Which government can compel a company follows from where it is incorporated. |
| Where data is processed | Not named: “the Owner's operating offices” and wherever processors are | European Union (Scaleway, France) | A European buyer filling in a vendor assessment cannot answer the question from their policy. |
| 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. |
| Self-hosting | Not possible: there is no self-hosted edition | Three services, same build as the cloud | Lock-in is the design there, not an oversight: their cloud is the only place it runs. |
| Workflow engine | Four commands: broadcast, wait, pause, abort | Send, run your own code, delay, wait for an event | A fixed delay covers a drip sequence. It does not cover “unless the invoice is paid first”. |
| Wait on an external event | No: pause only resumes on an API call you make | Yes, on a named event, with a timeout | Something in your application has to remember to un-pause the run, which is the state you wanted to hand over. |
| What a workflow is | JSON in their format, with their Liquid, on their engine | A function in your repository, in your language | Posting JSON through an API is closer to code than a canvas, and it is still not your code. |
| Billing unit | A delivery: one per channel, per user | A run, per recipient, any channels | 100 users on two channels is 150 deliveries by their own example, and 100 runs here. |
| Plans | Free 1,000 deliveries · Startup $249/50,000 · $99 per extra project | Free 500 runs · €19, €49, €149 | Their free tier is a tenth of the category's, and the step above it is $249 with nothing in between. |
| Channels | In-app inbox, web and mobile push, Slack, SMS, email | Email at beta; SMS, Telegram, Slack and push declared | The in-app inbox is what MagicBell is for, and Palumb has not declared one at all. |
| Certifications | GDPR compliance stated; no SOC 2, ISO or HIPAA named | None | The one comparison of the five where the audit-report question does not settle it in the other direction. |
| Status | Generally available, 1,000+ companies claimed | 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 MagicBell's own [pricing page](https://www.magicbell.com/pricing) and its delivery-counting FAQ, their [workflows product page](https://www.magicbell.com/workflows), their [security page](https://www.magicbell.com/security), [privacy policy](https://www.magicbell.com/privacy-policy) and [terms](https://www.magicbell.com/terms-and-conditions). 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 MagicBell?

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.

MagicBell is a notification inbox first: proprietary, hosted only, with a workflow engine of four commands and a bill that counts one delivery per channel per user. If what you need is the in-app bell, MagicBell is built for exactly that and Palumb has not declared one.

### Can a MagicBell workflow wait for an event?

No. Their engine has four commands: `broadcast`, `wait` for a fixed number of seconds, `pause`, and `abort`. `pause` suspends the run until something resumes it through the API, so your application has to hold the state and remember to make that call, which is the work you were trying to hand over. Palumb has a step that waits on a named event with a timeout, and the engine holds the state.

### Does MagicBell bill per channel?

Yes, and they put it in numbers themselves: “To count deliveries, we add up all the channels a user receives a notification on… if you send a notification to 100 users, all receive it in\_app, but only 50 receive an email; we count that as 150 deliveries.” Palumb counts one run per recipient regardless of how many channels the workflow touches, so the same work is 100.

### Is MagicBell open source?

No. MagicBell is proprietary software. Their client SDKs are on GitHub, as every vendor's in this category are, because otherwise nobody would import them. The engine that runs your workflows and holds your notification history is closed, and there is no self-hosted edition on any plan. Palumb publishes the whole delivery path under AGPL-3.0, and self-hosting is free.

### How much does MagicBell cost?

Free for 1,000 deliveries a month on one project, then $249 a month for 50,000 with $0.0025 per delivery after that, plus $99 for each project beyond five. Remember that a delivery is counted per channel, so a two-channel workflow reaches that ceiling twice as fast. Palumb is free to 500 runs, then €19, €49 and €149, with runs counted once per recipient.

### Where does MagicBell store my data?

Their privacy policy does not say. It states that data is processed “at the Owner's operating offices and in any other places where the parties involved in the processing are located”, and names no country, region or residency option. What is on the record is the company: MagicBell, Inc., 2261 Market Street, San Francisco, California. Palumb is operated in the European Union, on Scaleway in France, and the sub-processors are listed by name.

## 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 Knock](/compare/knock/)
    
    Richer workflow functions and an in-app feed. A New York company, and no self-hosting path at all.
    
-   [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 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/)