Skip to content
BeeBuzz Architecture: Designing for Minimal Trust

BeeBuzz Architecture: Designing for Minimal Trust

March 12, 2026

Building BeeBuzz, I kept coming back to one idea: design for the worst case, not the best one.

Not because I expect things to go wrong — but because assuming they might forces better decisions. No server is perfect. Dependencies have bugs. People make mistakes. So instead of pretending everything is secure, I designed BeeBuzz to limit the damage if something does break.

Keeping Scope Small

BeeBuzz does one thing: deliver notifications triggered by events.

I could have added chat, workflows, multiple roles. I didn’t want that. Fewer moving parts make it easier to understand what’s happening and keep the attack surface small. Notifications are plain text — emoji are fine, rich formatting is not. A narrow scope also makes the codebase easier to audit — which matters more than it might seem.

Encrypted Mode vs Trusted Mode

One of the early choices was supporting two modes — and making both feel like first-class options, not a “secure mode” and a “lazy mode.”

In privacy E2E mode, the sender encrypts the payload client-side before it ever leaves their device. The server receives ciphertext, stores it, and notifies the client. The client downloads and decrypts on demand — the server never sees the content.

But E2E is only possible when you control the sender.

If a notification is triggered by a third-party service — a webhook from a CI pipeline, an alert from a monitoring tool, an event from an external API — the payload arrives at the server in plaintext by definition. You can’t E2E-encrypt something you didn’t originate. In those cases, trusted server mode isn’t a compromise, it’s just the reality of how the web works. The server encrypts the attachment itself, stores it, and notifies the client. The client downloads and decrypts on demand, just like in E2E mode.

In both cases, the push notification never carries the attachment — only a reference to it. The file always lives encrypted at rest and is decrypted on device.

The two modes aren’t a hierarchy. E2E mode is for when you own both ends of the pipe. Trusted mode is for everything else — and it’s still treated carefully.

One thing worth noting: in both modes, the Web Push notification itself is encrypted in transit between BeeBuzz and your device (RFC 8291). The push provider — FCM, Mozilla, or any other — never sees the content. The difference between the two modes is only about what BeeBuzz server can read, not what the transport layer exposes.

Encryption on the BeeBuzz side is handled with age — but the details of that flow deserve a post of their own.

Privacy E2E mode
💻
Sender
Encrypts payload client-side, per target device
encrypts locally
🔒
BeeBuzz server
Stores ciphertext, notifies client via push — content is opaque
sees nothing
📡
Web Push provider
Notification re-encrypted in transit (RFC 8291) — provider sees only opaque bytes
VAPID · encrypted in transit
📱
Device
Decrypts notification, downloads and decrypts payload automatically
decrypts on device
Trusted server mode
🔗
API sender
Sends message and attachment — webhook, CI, external API
plaintext payload
🖥️
BeeBuzz server
Encrypts attachment per device, stores it, notifies client via push
encrypts per device · 24h TTL
📡
Web Push provider
Notification re-encrypted in transit (RFC 8291) — provider sees only opaque bytes
VAPID · encrypted in transit
📱
Device
Decrypts notification — attachment downloaded and decrypted on demand
decrypts on device

Metadata and Data Lifetime

Even encrypted messages leak information through metadata. I tried to minimize what’s stored: only what’s needed for delivery, no extra identifiers, temporary data cleaned up automatically.

Messages are never stored server-side — they’re delivered and gone. Attachments are the only thing that lives on the server, and they expire after 24 hours.

If data doesn’t need to exist, don’t keep it.

Why Web-Only

Native apps bring background services, persistent storage, app store rules — complexity I didn’t want. Staying web-only keeps the surface smaller and easier to reason about. It also means I can maintain this in my spare time without losing my mind.

Self-Hosted vs SaaS

The same core powers both. Self-hosting gives full control over infrastructure. The SaaS version exists because I use it myself, and for anyone who wants the same thing without running a server.

Making both work meant designing the system to behave predictably across different environments — which turned out to be a useful constraint in itself.

Auditability

Because BeeBuzz is open source, the architecture has to be easy to follow. One concrete example: I keep encryption and decryption confined to clearly defined boundaries, so there’s no ambiguity about what the server sees at any point. No logic scattered across layers, no implicit trust.

Anyone reading the code should be able to answer four questions without digging:

  • Where is data encrypted?
  • Where is it decrypted?
  • What does the server actually see?
  • When does data get deleted?

If those answers aren’t obvious, the design needs rethinking.

Constraints Are Intentional

No mobile apps. No feature bloat. No analytics. No complex multi-user flows.

These aren’t gaps to fill — they’re choices. Each one simplifies reasoning, reduces complexity, and reinforces the privacy model.

BeeBuzz isn’t trying to be a messaging platform. It’s meant to deliver secure notifications reliably. That focus guides every architectural decision.