Case Study · Operations · 2022 — 2024

Payroll & HR — auditable runs, every time

Scheduled payroll lifecycle from employee data to payout, with an auditable history of every run.

Spec Sheet

Role

Full-stack engineer

Timeline

2022 — 2024

Status

In production

Surface

HR dashboard + admin panel

Stack

Next.js · Node.js

Data

MongoDB · Job queue

01

Problem


HR teams were running payroll from spreadsheets — prone to manual errors, with no audit trail and no way to reproduce a past run. A miscalculation meant an employee underpaid, often discovered only weeks later. The cost was not just financial but trust.

02

Context & constraints


A multi-company HR platform used across organizations with different salary structures, allowances, and deduction rules. Each payroll run had to be fully deterministic — the same inputs must always produce the same output — and every step had to be reversible and explainable.

Determinismsame inputs always produce the same output
Audit trailevery state change is logged and attributed
Multi-tenancyeach company's data and rules are isolated
03

Architecture


Request path

HR admin

trigger run

Validation

employee data

Rules engine

salary calc

Approval

sign-off

Payout

bank transfer

Audit log

immutable

Failure recovery & consistency

Failed run

detected

Rollback

to draft

Fix input

HR corrects

Re-run

idempotent

04

Implementation


Frontend

  • ·Payroll wizard: draft → review → approve → pay
  • ·Employee records with salary history
  • ·Per-run audit viewer with change diff

Backend

  • ·Rule engine: gross → deductions → net per employee
  • ·Job queue for async payout processing
  • ·Immutable audit log on every state change

Data

  • ·Employee schema with versioned salary records
  • ·Payroll run document: snapshot at time of run
  • ·Audit entries append-only, never updated
05

Key decisions


01

Snapshot employee state at run time

Payroll calculations must be reproducible. Snapshotting the employee record at the moment of each run means historical runs stay correct even after employee data changes.

02

Approval step before payout

A mandatory sign-off before any bank transfer is initiated ensures a human reviews the run summary. Mistakes caught here are free; mistakes caught after payout are expensive.

03

Append-only audit log

Every status transition — draft, under review, approved, paid — creates a new audit record attributed to the actor. Retroactive edits are blocked; corrections create a new version.

06

Tradeoffs


Chose

·Snapshot-based run records for reproducibility

·Async job queue for payout resilience

·Strict approval gate before disbursement

Gave up

·Simpler live-query payroll (would lose history)

·Synchronous payouts (would block on bank latency)

·One-click pay without approval (too risky)

07

Outcome


0

payroll runs lost or unrecoverable after errors

100%

runs reproducible from stored snapshot + rules

hours → min

from run trigger to approval-ready