Self-hosted service
buzzkit-dev/buzzkit avatar
buzzkit-dev/buzzkit

BuzzKit: bring your own keys, orchestrate the notifications

The open source notification orchestration layer

383 stars21 forksTypeScriptAGPL-3.0

At a glance

What is it?
BuzzKit is an open source notification orchestration layer that separates provider credentials from delivery logic, giving you subscribers, targeting, preferences, scheduling, workflows, retries, and receipts through one API and one dashboard, though self-hosting currently means standing up five Cloudflare products alongside PostgreSQL and Tinybird.
Who is it for?
BuzzKit suits a team that already runs on Cloudflare, wants push notifications driven by events rather than by UI code, and would rather keep its provider credentials under its own control than hand them to a hosted vendor. It is a poor fit if your stack is not on Cloudflare, since the runtime assumptions are not abstracted, and a poor fit if you need several channels today, because only iOS push is implemented and everything else sits behind a roadmap.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.

Editorial analysis

You bring the keys, it brings the orchestration

The division of labour is the product. You supply the credentials for whichever push provider you use, and BuzzKit supplies the parts every notification system eventually grows: subscriber and device records, targeting, per-user preferences, scheduling, workflows, retries, and delivery receipts. That list is unglamorous and is most of the total cost of doing notifications properly, which is the argument for extracting it. The integration model is also deliberate. You are meant to integrate once and then be driven by events, with the SDK keeping users and devices in sync while your application and backend report what happened, and a workflow layer deciding what actually goes out and when. Receipts close the loop, which is the piece most hand-rolled implementations lack and the piece support teams ask for first.

Self-hosting needs five Cloudflare products and two databases

Here is the honest part. The self-hosting section says a complete guide is coming soon, and in the meantime a deployment requires a Cloudflare account for Workers, key-value storage, Queues, Durable Objects, and Hyperdrive, together with PostgreSQL and Tinybird. That is five distinct Cloudflare products with their own binding model, plus two datastores, before a single notification is delivered. The project does say it plans to simplify this in future releases, which is the right thing to say but does not help today. The practical read is that self-hosting is currently viable for a team already committed to Cloudflare and awkward for anyone else, since the runtime assumptions are not abstracted behind a port. Note also that the same code runs as a hosted service, so the hosted route is the lower-friction option if the infrastructure list is a barrier.

One grammar package keeps the dashboard honest

The workspace layout reveals what the team considers load-bearing. A dedicated schema package holds the grammars that both the API and the dashboard validate against, covering workflows, sources, and imports. That is a small decision with large consequences. In most dashboards the front end grows its own idea of the data model and drifts until someone notices a field the interface can send that the server rejects. Here the same definitions are compiled into both, so a workflow the interface can construct is a workflow the API accepts. Alongside it sits a typed API client that the dashboard uses rather than hand-written request code, and a separate database package holding the schema and its migrations through an object-relational mapper. The pattern is unglamorous duplication avoidance, and it is why the two apps can move independently.

The event stream is defined as code

Analytics in this project is not a bolt-on. A dedicated package treats the event stream as code, and deploying it is a versioned push rather than a set of manual dashboard clicks. The instruction is specific: run the push once for every fresh container so its event tables and endpoints get loaded, which tells you the schema is deployed as artefacts that must be initialised per environment. Locally, Docker Compose brings up PostgreSQL on one host port and Tinybird Local on another, with named volumes for both the database data and the analytics data, and a separate volume for the metadata service that Tinybird keeps in Redis. Health checks are configured for both, with a deliberately long start period on the analytics container, which reflects how long the local analytics stack takes to become genuinely ready to answer.

Local start is one command plus two migrations

The development path needs Bun and Docker, and then it is a short fixed sequence:

sh
bun install

bun db:up

cp apps/api/.dev.vars.example apps/api/.dev.vars
cp apps/web/.dev.vars.example apps/web/.dev.vars

bun run --cwd packages/database db:migrate
bun run --cwd packages/tinybird push

bun dev

Three secrets have to be set in the API's local environment file before the first start: an auth secret, a credential encryption master key, and an alphabet used to generate short identifiers. The example file explains how to produce each, which is the right call for values that are easy to get wrong. Once running, four services sit on four different ports, so the API, dashboard, marketing site, and documentation each get their own address, with an OpenAPI browser mounted on the API. The command surface is deliberately small: start everything, run tests, lint, type-check, and format.

Only iOS ships, and the rest are roadmap boxes

The delivery reality is narrower than the feature list suggests. iOS push is the one channel that works today, and even that has its own repository, since the mobile SDK lives apart from the server monorepo. Everything else is an unchecked box on the roadmap: an Android SDK sending through the primary Android push service, email through a provider you supply, SMS, web push, in-app messaging, and experimentation in the form of A/B tests applied to messages and workflow steps. The architectural claim behind those boxes is that each new channel arrives as a connector sharing the same subscribers, segments, topics, and workflows already in place, so adding a transport should not mean re-implementing targeting. That is the right design, but it is a promise rather than a capability today, and anyone planning an SMS or email launch needs to build that path themselves.

Pull requests are closed to outsiders

The contributing section is unusual and worth reading before you start. The project describes itself as still in beta and says it is being careful about what goes in, and as a result pull requests are limited to the core contributors, with issues named as the best way to help. Bug reports and feature proposals both route to the issue tracker with pre-applied labels, and the project says every issue is read. So the contribution model is consultative rather than open, which is a defensible choice for a pre-release project handling credential encryption, but it does mean the usual path of submitting a fix will be closed. Around that, the toolchain is thorough for an early repository: a task runner driving builds and tests across workspaces, a changesets-based release flow with separate SDK versioning, a formatter, a linter with a custom conventions checker, unused-export detection, a spell checker, and commit hooks wired through a package manager lockfile.

Editorial conclusion

BuzzKit suits a team that already runs on Cloudflare, wants push notifications driven by events rather than by UI code, and would rather keep its provider credentials under its own control than hand them to a hosted vendor. It is a poor fit if your stack is not on Cloudflare, since the runtime assumptions are not abstracted, and a poor fit if you need several channels today, because only iOS push is implemented and everything else sits behind a roadmap. Before planning a self-hosted deployment, budget for the operational weight of five Cloudflare products plus two databases, and treat the missing self-hosting guide as a real gap rather than a formality.

Frequently asked questions

What is BuzzKit?

An open source notification orchestration layer. You supply the provider keys, and it provides subscriber management, targeting, preferences, scheduling, workflows, retries, and delivery receipts through one API and one dashboard.

What does self-hosting BuzzKit require?

A Cloudflare account for Workers, key-value storage, Queues, Durable Objects and Hyperdrive, together with PostgreSQL and Tinybird. The project states that a complete self-hosting guide is still to come and that it plans to simplify the setup.

Which notification channels does BuzzKit support?

iOS push is supported today, with the iOS SDK kept in a separate repository. Android through its primary push service, email, SMS, web push, in-app messaging, and experimentation are all listed as future connectors sharing the same subscribers and workflows.

Can I submit a pull request to BuzzKit?

Not currently. The project is in beta and limits pull requests to core contributors, naming issues as the way to help instead. Bug reports and feature proposals both go to the issue tracker with labels applied.

Official sources

  1. buzzkit-dev/buzzkit on GitHub
  2. Issues
  3. License: AGPL-3.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/buzzkit-dev-buzzkit.svg)](https://hysenlabs.com/projects/buzzkit-dev-buzzkit)