Corex360
EngineeringMay 14, 20268 min read

Thousands of businesses, one core: scaling a multi-tenant architecture

Data isolation, a single core serving thousands of tenants, event-driven real-time synchronization, and per-tenant KVKK compliance — from a production point of view.

By Şevket Erer

A multi-tenant SaaS looks like a single application from the outside; on the inside, it's the discipline of carrying thousands of businesses' data on the same core without ever letting it touch. This is also the perennial topic of Corex360's monthly engineering webinar: how to build a system with a single codebase and a single infrastructure that still feels, to each tenant, like a world of its own.

Isolation: schema or row?

The first and most critical decision is data isolation. There are two main approaches: a separate schema for each tenant (schema-per-tenant), or tagging every row with a tenant_id in shared tables (row-level). The schema-based approach gives strong physical separation and easy backups, but managing tens of thousands of schemas makes migrations heavy. The row-based approach is operationally lightweight and scales; but a single missing WHERE clause is a disaster. In practice the hybrid wins: row-based isolation for most modules + row-level security policies (RLS) enforced at the database level, and logical separation for large enterprise tenants.

What matters is enforcing isolation at the lowest possible layer, not by trusting application code. A developer who forgets to add the tenant_id filter to every query by hand will, one day, leak another tenant's data. That's why the filter is embedded in the database policy and the shared query layer; even if a developer wanted to skip it, they couldn't.

In multi-tenant architecture, security is not a feature but the default behavior; not the exception, but the rule.

One core, real-time sync

In Corex360, a message arriving from WhatsApp must appear at the same moment in the inbox, on the CRM card, and on the BI dashboard. We solve this not by constantly polling every screen, but with an event-driven backbone: when something happens — a new message, an issued invoice, a moving vehicle — the system publishes an event, the relevant modules listen for it and update themselves. Even while a single core serves thousands of tenants, each tenant's events travel only within its own boundaries.

This architecture keeps modules loosely coupled. The vehicle tracking module doesn't need to know the inventory module's internal structure; both speak the same event language. Adding a new module means adding a new listener to the stream, not rewriting the core. The secret to scaling is managing not size, but independence.

Per-tenant authorization and KVKK/GDPR

KVKK in Turkey, GDPR in Europe — both demand a clear answer to the question of 'who owns the data and who may see it.' In a multi-tenant system, this means two-layered authorization: first the tenant boundary (a business's user can never access another business's data), then roles within the tenant (the field supervisor sees vehicle data, the accountant sees invoices, not everyone sees everything).

The practical face of compliance is auditability: who accessed which data and when; when a tenant's data is asked to be deleted, that and only that tenant's trace is actually erased; data retention periods can be enforced per tenant. A good multi-tenant architecture carries KVKK not as a compliance layer pasted on afterward, but as a natural consequence of the isolation decision.

Related posts

Leave the chaos behind,
build the order.

Certifications & Compliance
ISO 27001Information Security
ISO 9001Quality Management
SOC 2 Type IICompliance
KVKKData Protection