Skip to content
Case study · ZekoHR

We built ZekoHR as an HR platform where tenant isolation is enforced once

ZekoHR runs payroll, attendance, recruitment, documents, expenses and grievances for many companies on one codebase. This study covers how we kept tenants apart, kept payroll auditable and decided where AI was allowed.

Updated 6 Nov 2026 · 8 min read · By Teksmobile engineering

  • Product: ZekoHR
  • Web and mobile
  • Multi-tenant SaaS
ZekoHR admin dashboard with a morning greeting banner, a list of items needing attention and a who-is-on-leave panel

Context

Most growing companies run HR on a mix of spreadsheets, a payroll bureau, email threads for leave and a shared drive for contracts. Each tool holds a different version of the employee. ZekoHR is our own HR platform, built to be sold as software-as-a-service to many companies at once: payroll, attendance, recruitment, document management, expenses and grievance handling in one system, with each company configured rather than coded.

The product sits in the HR technology space, and the decisions below are the ones we now carry into client work in that sector and in any multi-tenant product that holds sensitive personal data.

The challenge

  • Isolation. An HR system holds salaries, bank details, medical notes and grievance cases. A cross-tenant leak would end the product.
  • Payroll correctness. Every payslip must be reproducible months later and explainable line by line. Rules change between periods and vary by jurisdiction.
  • Need-to-know access. Employees, managers, HR, finance and administrators all see different slices. Grievances need restricted visibility even from HR administrators.
  • Auditability. Who changed a salary, when, and what was it before?
  • Where AI fits. Recruitment and policy questions benefit from language models. Payroll must never depend on one.

What we built

  • Multi-tenancy. One codebase. The tenant is resolved at sign-in, carried in the session and applied by the data-access layer. No repository method can be called without a tenant scope.
  • Payroll engine. Rules are versioned data, not code. A dry run shows the difference from the previous period before anyone approves. Approved periods lock, and every payslip stores the rule-set version and the inputs that produced it.
  • Attendance and leave. Clock-in from web and mobile, timesheets, leave balances and approvals that feed payroll directly.
  • Recruitment. Job postings, a pipeline per role, interview scheduling, and AI-assisted parsing of CVs into structured fields that a recruiter confirms.
  • Documents. Contracts, letters and certificates in encrypted storage, served through short-lived signed URLs with a per-document access list.
  • Expenses. Claims with receipts, policy limits, approval chains and export into the payroll run.
  • Grievances. Cases with a restricted access list, a separate audit trail and no appearance in general reporting.

Architecture

ZekoHR architecture: tenants pass through identity and role resolution, then a data-access layer that requires a tenant scope on every query, before reaching the six modules and shared services Company Aown users · config · rule sets Company Bown users · config · rule sets Company Cown users · config · rule sets Identity & role resolution tenant resolved once at sign-in · role (employee, manager, HR, finance, admin) attached to the session session carries tenant + role Data-access layer every query requires a tenant scope · cross-tenant attempts are tested in CI · row-level restrictions for grievances scoped reads and writes only Payroll enginedeterministic · versioned rules · no LLM Attendance & leaveclock-in · timesheets → payroll RecruitmentAI CV parsing → human review Documentsencrypted · signed URLs · per-doc ACL Expensesclaims · limits · approvals Grievancesrestricted access list every change recorded Audit log (append-only) Notifications Encrypted file store
Three companies, one codebase. Tenant scope is decided at sign-in and enforced by the data-access layer, so no module can reach another company's rows by accident.

Key decisions

1. One codebase, with the tenant filter in a single layer

We considered a database per tenant. It isolates well but makes migrations, reporting and onboarding slow. We chose shared tables with a mandatory tenant scope in the data-access layer, backed by continuous-integration tests that deliberately try to read across tenants. The scope is impossible to forget because the repository API has no method without it.

2. Payroll is a deterministic engine

Rules live as versioned data with effective dates. A payroll run is a pure function of the rule-set version and the inputs, so re-running an old period gives the same result. The dry run produces a diff against the previous period, which is where most mistakes are caught. No language model is anywhere near this path.

3. Need-to-know access rather than role-to-everything

Roles grant broad access; grievances subtract from it. A case is visible only to the people named on it, and an HR administrator who is not named cannot see that it exists. The audit trail for cases is separate, so a routine audit export does not reveal them.

4. An append-only audit log

Every change to a salary, contract, claim or role writes a before-and-after record that cannot be edited. This turned out to be the feature finance teams ask about first.

5. AI only at the edges, with a human in the loop

Language models parse CVs into structured fields, answer policy questions with citations to the company's own handbook, and draft job descriptions. In every case a person confirms the output before it becomes a record. The pattern is the same one we use in recruiting AI engagements, and it keeps the product on the right side of data-privacy expectations for employee data.

6. Onboarding by configuration

A new company is a set of configuration records: pay elements, leave types, approval chains, document templates. Nothing is deployed to add a tenant.

Outcome

Companies are onboarded by configuration rather than by a project. Payroll runs are reproducible and explainable line by line, and audit questions are answered from the log rather than from memory. AI features in recruitment and policy support were added without any change to the tenant model or the payroll engine. The design has held as the product has grown in modules and in companies.

What this means for you

If your product holds sensitive data for many customers, decide where tenant scope is enforced before you write a feature, make the audit log append-only from day one, and keep language models out of any calculation that someone must reproduce later. We bring those rules to HR tech builds, to multi-tenant SaaS in other sectors, and to AI implementation work where a model is being added to an existing system of record.

FAQ

Frequently asked questions

Is ZekoHR available to use?

Yes. ZekoHR is a live HR SaaS product covering payroll, attendance, recruitment, documents, expenses and grievances for multiple companies on one platform. Contact us for a demo or to discuss a deployment for your company.

Why is there no AI in the payroll engine?

Payroll must be deterministic, reproducible and explainable to an auditor. A language model cannot promise any of those. We use AI at the edges, for CV parsing, policy questions and drafting, where a human reviews the output. Our AI governance work follows the same principle.

Can you build a multi-tenant SaaS like this for another domain?

The tenant model, role-based access, audit log and configuration-driven onboarding transfer to any product that holds sensitive data for many customers. Start with an engagement model that fits, usually a discovery sprint.

Talk to us about your AI project

Tell us what you are trying to do, which systems are involved and what is in the way. We reply within one business day with an opinion and a suggested next step.