1
0 Comments

How event sourcing changes what multi-tenancy even means

Most multi-tenant SaaS is just a WHERE tenant_id = ? bolted onto a relational schema. It works until it doesn't — GDPR erasure requests, per-tenant audit trails, debugging "why did this break for Acme but not Beta Corp" at 2am.

We went a different direction with Kumiko: every write is an event in a per-tenant stream.

What that buys you:

Audit log for free. The stream is the audit log. No separate table, no "we should really add logging here someday."

GDPR erasure without surgical DELETEs. When a user requests erasure under Art. 17, we emit a UserErasureRequested event. The projection rebuild skips that user's data. Backup tapes? Handled separately, declaratively. No DELETE FROM ... WHERE user_id = ? scattered across 40 tables.

Debugging across tenants. You can replay Acme's event stream up to the moment before a bug appeared. No guessing what state the DB was in.

Feature tiers per tenant without schema branches. A tenant on the free tier just doesn't have certain event handlers registered. No if/else in business logic.

The downside is real: event sourcing adds complexity upfront. You have to think in terms of projections, not tables. It's not right for every app.

But for multi-tenant SaaS where GDPR, audit trails, and per-tenant customization are first-class concerns — it's the best foundation we've found.

We open-sourced the framework that makes this practical for TypeScript devs: kumiko.rocks

Happy to answer questions about the tradeoffs.

on June 29, 2026