Mohammad Jahangir
← All articles
Mohammad Jahangir

Designing Multi-Tenant Workforce Management Software

How Opperiq's data model isolates every client's workforce data on shared infrastructure, and why that decision has to happen before any feature work.

NestJSPostgreSQLPrisma

The problem with single-tenant thinking

Opperiq exists because field-operations companies run attendance, scheduling, fleet, and payroll across spreadsheets and disconnected point tools. The obvious first build for a platform like this is single-tenant: one client, one database, one deployment. That works until client two shows up, and then every table needs a client identifier retrofitted onto it, every query needs a filter added, and every place that filter is missing becomes a data-leak risk between clients.

The alternative is to decide upfront that Opperiq would serve multiple tenants — companies, in this case — on one shared codebase and one shared database, with isolation enforced at the schema level rather than left to application code to remember.

What the data model actually does

Every workforce record in Opperiq — employees, managers, attendance logs, shifts, vehicles, payroll entries — is scoped to a tenant at the schema level in PostgreSQL, managed through Prisma. Role-based access control sits on top of that boundary: a manager at one company can never query, even accidentally, a record belonging to another company, because the tenant scope is enforced in the data layer, not just in UI routing.

This is the kind of decision that's cheap to make correctly at the start and expensive to retrofit later. Every feature built after this point — geofenced attendance, task workflows, fleet maintenance — inherits tenant isolation automatically instead of needing it re-implemented per feature.

Why NestJS for this specifically

NestJS's module system maps naturally onto Opperiq's feature boundaries — attendance, scheduling, fleet, payroll, finance — each as a separate module with its own service and controller layer, all still operating within the same tenant-scoped data access pattern. As the platform grew past a handful of modules, that structure is what kept the codebase navigable instead of turning into one large Express app with implicit conventions.

Where this connects to the rest of the platform

The tenant-isolated backend is what makes Opperiq's other systems possible without re-solving the isolation problem each time: the React Native field app authenticates into a specific tenant context, the AI face-verification service checks identity within that tenant's employee records, and the OCR receipt pipeline writes expense data into that tenant's finance module — never anyone else's.

Related project

Opperiq

A multi-tenant operating system for field workforces.