Nexa People
A multi-tenant HR platform: employee records, attendance, leave and payroll on one data model.
- 49
- Employees on the demo tenant
- 10
- Filters
- 1
- Source of truth
What they came with
Most small HR teams keep the same employee three times over: once in a personnel folder, once in an attendance sheet, once in the payroll workbook. When a salary changes mid-month someone has to remember all three, and the payroll run turns into a reconstruction job rather than a calculation. Nexa People puts one record underneath all of it, so attendance, leave and payroll read the same contract, the same salary and the same history. It is multi-tenant, so a group running several companies keeps them apart without running several systems.
What the engagement covered
- Filterable employee directory with role templates and documents
- Bulk import, export and credential sending
- One record feeding attendance, leave, payroll and performance
- Gross, tax and net pay computed from attendance and leave
- Approval, payslip sign-off and disbursement in one flow
- Salary advances, claims and adjustments handled in the same module
Technical detail
Tenancy enforced at the row
Every table carries a tenant id and Postgres row-level security applies it, rather than trusting each query to remember a where clause. The tenant is resolved once from the session in a NestJS request-scoped provider and set on the transaction, so a service method has no way to run without one.
Salary and role kept as history
Contract, role and salary changes append effective-dated rows instead of overwriting the previous value, and payroll reads the row that was valid on each day of the period. A back-dated correction therefore recomputes cleanly and still leaves what was actually paid visible.
Payroll as a resumable run
A run is a BullMQ job that computes one line per employee into a draft state; approval freezes the snapshot and generates payslips from it. Lines are idempotent on run and employee, so a worker that dies halfway resumes without paying anyone twice.
Attendance is the payroll input
Clock events are append-only and leave approvals are reconciled against them, so the payroll run never invents a day. Days with neither attendance nor approved leave are flagged before the run rather than quietly paid or quietly dropped.
The stack
Interface
Application
Data and jobs
Run and deploy
- Sector
- HR platform
- Audience
- HR and payroll teams
- Shape
- Built, shipped and run by us
- Stack
- Next.js, NestJS, PostgreSQL
Something like this to build?
Tell us what runs today and where it hurts. An engineer reads it and replies.

