02 / 06
Discipline
Data Engineering & Database Administration
Two things that usually get separated and should not be. The first is designing how your data is stored, related, secured, and moved: schemas, migrations, the queries that carry the load, and the rules that keep one customer’s information away from another’s. The second is keeping that database alive, which means backups that have actually been restored, performance that does not quietly degrade, and recovery that works on the day it is needed.
Most providers are enthusiastic about the first and vague about the second.
Approach
Positions we hold
How we approach it.
Tenant isolation belongs in the database
If your platform serves multiple customers, the most consequential decision you make is where isolation is enforced. The common answer is the application layer, where every query filters by tenant and correctness depends on every developer remembering the filter, forever. One missed clause in one endpoint is a data breach you find out about from a customer.
We put it in the database. Row-level security means the database refuses to return another tenant’s rows regardless of what the application asks for.
What that costs
Row-level security has a query-planning cost, complicates some administrative operations, and needs care with connection pooling and session context.
We think that is a good trade for removing an entire category of breach, and we would rather say what it costs than present it as free.
Shared schema or per tenant is a decision
Most platforms have whichever model the first developer implemented, and no record of a decision. Shared schema is cheaper to operate, simpler to migrate, and better with many small tenants. Per-tenant databases give real blast-radius isolation, per-customer backup and restore, and a straightforward answer on data residency.
They also multiply migration and operations work by the number of tenants. Pick against the customers you actually expect.
One codebase can serve both
One platform we run routes tenants across SQLite and per-tenant SQL Server from a single codebase and a single release cycle, because different deployments of the same product had genuinely different requirements.
That is not a trick. It follows from treating tenancy as an architecture decision rather than a default.
Migrations are part of the product
A schema change that cannot be applied without downtime is a design problem rather than an operations problem. Migrations are versioned, reviewed, applied through the pipeline, and written to be reversible where reversal is possible and explicitly one-way where it is not.
A backup nobody has restored is a belief
We test restores into an isolated environment on a schedule and record what the restore actually took. Recovery time is a number you want to learn before an incident.
The same applies to indexing. Reports that time out are rarely a hardware problem, and finding the cause is usually a matter of looking rather than guessing.
Where we stop
We are not a data science or analytics practice. We build and run the operational data layer, including the reporting a system needs to explain itself. If you want a warehouse, a modelling layer, and a BI practice on top, we will build the pipelines that feed it and tell you that the analytics work belongs with a specialist.
Stack
What actually runs in production.
SQL Server
Per-tenant SQL Server
Postgres
Row-level security
SQLite
Redis
Entity Framework Core
CQRS
SQL Server Reporting Services
Kafka
Supabase
Firebase
Versioned migrations
Engagements
Typical shapes this takes.
Tenancy design
Choosing and implementing the isolation model, before or during a build. Days to weeks, and an order of magnitude cheaper before launch than after.
Performance and cost work
Finding what actually got slow, and what is driving the bill on a system that has grown.
Database administration on a retainer
Backups, restore testing, index maintenance, recovery planning, capacity.
Deliverables
What you get.
A written tenancy decision
With the trade-offs stated and the reasoning kept.
Migration history under source control
Nobody has to reconstruct what state the database is in.
Isolation policies in the database
Row-level security where isolation matters.
A tested restore
With a recorded recovery time, rather than a screenshot of a backup setting.
Before and after on remedial work
What each query did, what it does now, and why it changed.
Ownership
Schema, migrations and data are yours throughout.
Reading
Related reading.
The strongest seam here is routing tenants across SQLite and per-tenant SQL Server from one codebase, and the case for row-level security over application-layer filtering. Those pieces will be linked here as they are published.
Claer & Volker
453 Winifred Yell St, Garsfontein
Pretoria, South Africa
info@claervolker.com
© 2026 Claer & Volker
·
·