For a full example answer with detailed architecture diagrams and deep dives, see our Design Payment System guide. While the payment guide focuses on transaction processing, many of the same patterns around multi-step workflows, idempotency, ledger design, and ACID guarantees apply directly to payroll computation and disbursement.
Also review the Message Queues and Databases building blocks for background on durable workflow orchestration and transactional financial storage.
Design a payroll system that can calculate employee salaries, manage tax deductions, process payments, and adapt to different countries with varying tax laws and regulations. Think of products like ADP, Workday, Gusto, or Paychex where HR teams configure employee data and compensation, run payroll on a recurring schedule, review results, approve, and execute payments to employees and tax authorities.
The core challenge blends correctness, compliance, and money movement. Payroll is a multi-stage batch workflow: gather time and compensation data, apply country-specific tax rules, calculate gross-to-net pay, get approval, initiate payments via banking rails, and generate payslips and compliance reports. Every step must be idempotent, auditable, and versioned. Tax rules change over time and vary by jurisdiction, so the system must support effective-dated rule versions that can be reproduced historically. Interviewers test how you model effective-dated data, orchestrate multi-step batch processes, integrate with external payment providers, and maintain a clear audit trail with safe failure recovery.
Based on real interview experiences, these are the areas interviewers probe most deeply:
A payroll run is not a single operation but a pipeline with dependent stages: ingesting time and compensation data, computing gross-to-net, approval, payment initiation, and filing. Interviewers want to see durable orchestration with clear recovery from partial failures.
Hints to consider:
Tax laws change, and the system must apply the rules that were in effect during the pay period, not the current rules. Interviewers probe whether you can reproduce historical calculations exactly.
Hints to consider:
Moving money to employees and tax authorities is the most critical and dangerous step. Interviewers expect explicit idempotency and failure handling for interactions with external banking rails.
Hints to consider:
payroll_run_id + employee_id) and pass it to the payment providerFinancial regulators require a complete, reproducible history of every payroll computation and payment. Interviewers assess whether your design supports this.
Hints to consider:
Begin by confirming scope. Ask whether the system needs to support multiple countries or a single jurisdiction. Clarify the expected number of companies and employees. Determine whether the system handles payment rail integration or treats it as an external dependency. Verify whether off-cycle payroll (bonuses, corrections) is required. Ask about the consistency model: can employees see a pending status briefly, or must payment confirmation be synchronous? Establish whether the focus is on the computation engine, the payment flow, or the full end-to-end system.
Sketch the core components: an Employee Service that manages employee profiles, compensation, and tax elections in PostgreSQL with effective-dated records; a Payroll Engine that computes gross-to-net calculations using versioned tax rule configurations; a Workflow Orchestrator that manages the multi-stage payroll run lifecycle; a Payment Service that integrates with external banking APIs using the outbox pattern; a Ledger Service that maintains an immutable record of all financial transactions; and a Reporting Service that generates payslips and compliance documents from run snapshots. Use Kafka as the event backbone for workflow transitions, payment status updates, and downstream notifications.
Cover payment processing: the Payment Service reads from the outbox, calls the banking API with an idempotency key, records the result in the ledger, and updates the employee's payment status. Discuss reconciliation: a daily job compares bank settlement files against the internal ledger and flags mismatches. Address multi-country support: abstract the tax calculation behind a country-specific rules engine interface so adding a new jurisdiction requires only new configuration, not new code paths. Cover monitoring: track payroll run duration, computation failures per employee, payment success rates, and reconciliation discrepancy counts. Mention disaster recovery: replicate the database synchronously, archive run snapshots to object storage, and ensure Kafka retains events for replay. Touch on scaling: partition payroll computation by company, run large companies in parallel batches, and use Redis for caching frequently accessed tax tables and exchange rates.
Walk through a payroll run for a 500-employee company. The HR admin triggers a run for the current pay period. The Workflow Orchestrator creates a run record in "draft" state, gathers employee data and time records, and transitions to "computing." The Payroll Engine fetches the applicable tax rule version for the pay period, iterates over employees, and for each calculates: gross pay from salary and hours, federal and state tax withholdings using the effective-dated tax tables, benefits deductions, and net pay. Results are stored as an immutable computation snapshot linked to the run. The run transitions to "review" and the admin previews the results. If adjustments are needed, the admin can modify inputs and re-trigger computation (idempotent). On approval, the run transitions to "approved" and payment processing begins. The Workflow Orchestrator emits per-employee payment tasks to the Payment Service. Discuss how individual employee failures are handled: the employee is marked as failed, the rest proceed, and a retry mechanism allows reprocessing failed payments without re-running the entire batch.