A provincial council coordinates dozens of small City Councils that lack the resources to run their own systems. The natural solution is to deploy a single piece of software serving them all. The critical technical challenge is: how do you make sure that no City Council can see the others' data?
This is the central question in multi-tenant design for the public sector, and this article describes how we approach it at Labrax.
Three multi-tenancy patterns
There are basically three strategies for serving multiple clients (tenants) from the same application:
1. Database-per-tenant (physical isolation)
Each client has its own, completely separate database. Maximum isolation, but high operational cost: managing 30 databases for a provincial council with 30 municipalities is complex to maintain.
2. Schema-per-tenant (logical isolation)
A single database, but each client has its own schema. A balance between isolation and cost. A good option when there are few clients but they need clear separation.
3. Shared database with tenant_id (column-level isolation)
All clients share the same tables, but every record has a tenant_id field identifying its owner. The application always filters by that field. It is the most operationally efficient pattern, but it requires absolute discipline to avoid data leaks.
The hierarchical level: parent and child tenants
A provincial council is not just a set of equal tenants. It is a hierarchical structure:
- The Provincial Council is a tenant with aggregated visibility (it can see indicators and statistics for every municipality in the province).
- Each City Council is a child tenant with visibility only of its own data.
- Some Associations of Municipalities may be intermediate tenants, with partial visibility of their member City Councils.
This hierarchy is not trivial to implement. Every read operation must evaluate the user's access level and return data at the appropriate level of detail:
- A user from City Council X sees the individual data for their municipality.
- A Provincial Council user sees aggregated indicators for the whole province, but not individual data about specific residents (this is very important under the GDPR).
- A Provincial Council superuser with explicit, signed authorisation can see individual data for a specific municipality, but this is recorded in the audit log.
Encryption: one key per tenant
Encryption of data at rest is mandatory under ENS High. The question is: a single key for the whole database, or one key per tenant?
We use one key per tenant. This means that even if someone had physical access to the server, they could not read the City Councils' data without also having the corresponding keys, which are stored separately in an HSM (Hardware Security Module). If a tenant asks to leave the service, we can guarantee cryptographic destruction of its data simply by deleting its key.
Access control: RBAC + ABAC
Control over who can see what is based on two combined models:
RBAC (Role-Based Access Control)
Users have roles (municipal administrator, operational officer, technician, manager) and each role has a defined set of permissions. An officer can query but not approve. A manager can approve within their tenant but not outside it. And so on.
ABAC (Attribute-Based Access Control)
On top of RBAC, rules based on resource attributes are added. For example: "a user can only see records where tenant_id = su_tenant". These rules are evaluated on every request and are what guarantee real isolation.
The combination is what makes the system complete: RBAC defines what the role can do in the abstract; ABAC defines which specific resources it can act on.
Auditing: the log is the contract
In the public sector, auditing is not optional. Every critical operation generates an entry in the audit log with:
- Who carried out the operation (user and tenant).
- What they did (type of operation).
- On which resource.
- When (timestamp accurate to the millisecond).
- From where (source IP, browser user agent).
- Outcome (success, failure, error code).
This log is kept for at least 24 months and is immutable: once an entry has been written, it cannot be modified or deleted. If an administration needs to prove that an operation was (or was not) carried out, the log is the evidence.
When a City Council leaves
An important architectural decision: what happens when a tenant leaves the service?
Our policy is as follows:
- The tenant requests to leave with notice (typically 6 months, depending on the agreement).
- A complete export of its data is generated in a standard format (structured JSON + attached files).
- The tenant checks that the export is complete and signs to confirm.
- Cryptographic erasure is carried out: the tenant's encryption key is destroyed.
- The data remain physically in storage for a further 30 days (security retention), but are inaccessible without the key.
- After 30 days, final physical deletion is carried out.
This process guarantees that the departing tenant receives all its data and that nobody (not even us) can recover them afterwards.
The operational side: how the system is run
Once in production, day-to-day operation involves:
- Deployments: we apply application updates to all tenants at once, but each keeps its own configuration (catalogues, parameters, integrations).
- Data migrations: when there is a schema change, tenants are migrated one by one, with automatic rollback if something fails.
- Monitoring: each tenant has its own health dashboard (latency, errors, usage). If one tenant has problems, it is isolated without affecting the others.
- Backups: daily backups per tenant, with 30-day retention for quick recovery and 12 months for legal compliance.
What changes if your provincial council wants to deploy this
If you run a provincial council and are evaluating supra-municipal software:
- Ask the supplier about its data isolation model. Database-per-tenant, schema-per-tenant or shared-with-tenant_id. Any answer is acceptable, but it must be clear and documented.
- Ask to see real audit logs from a tenant in production. If they cannot show you them, there is a problem.
- Ask how a tenant's exit is handled. If the answer is vague, there will be trouble the day your provincial council wants to change supplier.
- Ask about GDPR between tenants: what happens if one City Council's data controller requests information that cross-references another's data?
These questions separate the suppliers that have genuinely thought through multi-tenant architecture from those that have added a tenant_id field to their tables and call it "multi-tenant".






