Skip to content
Case 02Multi-tenant platform

A church management system rebuilt as a multi-tenant SaaS platform — a separate database per organisation, its own control plane, and a recovery story that has actually been tested.

Role
Architecture & full build
Tenancy
Database per organisation
Deployed for
6,400 members
Status
Live in production
raeetna.app / dashboard
Members
6,400
Households
1,900
Families
1,018
Attendance59ms
Tenants
st-mark.raeetna.appok
st-george.raeetna.appok
st-mary.raeetna.appok
st-antony.raeetna.appok
st-bishoy.raeetna.appok
st-takla.raeetna.appok
db per tenant
Interface preview2025

The problem

One church, thousands of people, and records held in a way nobody could query: households, families, services, pastoral history. The first version worked for a single organisation — but every new church meant another copy to deploy, another database to nurse, and no safe way to share a codebase between them.

It also had to be fast enough for daily use and trustworthy with sensitive personal data. A dashboard that takes five seconds gets abandoned; a backup nobody has restored is not a backup.

The architecture

Database per tenant, plus a control plane

Each church gets its own database; a separate control plane owns provisioning, tenant records and platform-level state. Isolation is structural, not a WHERE clause someone can forget.

Tenant resolved from the request host

The host on the incoming request decides which tenant connection is used, which makes custom domains per church a configuration step rather than a code change.

Backups at a second provider

Independent copies kept away from the primary infrastructure, so losing an account or a region does not mean losing the data.

Recovery drilled, not assumed

A full restore was rehearsed end to end: 23,717 documents brought back clean, zero failures. The drill is repeatable, which is the only reason to believe it.

Making it fast

Performance work was measured, not guessed at. The analytics behind the dashboard were the worst offender — aggregations doing far more work than the answer required.

Core analytics queries1,675ms59ms
Dashboard load5.3s3.5s
Restore drill23,717 docs0 failures
0
members
0
households
0
families
faster core analytics
raeetna.app / dashboard
Members
6,400
Households
1,900
Families
1,018
Attendance59ms
Tenants
st-mark.raeetna.appok
st-george.raeetna.appok
st-mary.raeetna.appok
db per tenant
raeetna.app / household
Record
restore drill23,717 / 0 fail
StackNode.jsMongoDBReactDB-per-tenantOffsite backupsCustom domains
Next case
JoSam Content Hub
Publishing to four platforms from one place