WhatsApp us

Blog6 min read29 Oct 2026

Payroll and CPF calculations: how we build and test them

Payroll engines fail at edge cases, not averages. How we build CPF calculations from the rules and test them against hand-computed cases before payslips issue.

Payroll and CPF calculations: how we build and test them

By KYN AI Advisory Team — AI implementation specialists, Singapore

A payroll engine is a set of rules applied to a table of people. The rules are public. The risk is in the edge cases: a mid-month joiner, a bonus that crosses a wage ceiling, an employee who turns 55. We build the CPF calculation as pure functions, one rule per function, and test each against cases computed by hand and checked against the CPF Board's published rates. Nothing reaches a payslip until those tests pass, and a named person approves every payroll run.

What does a payroll engine have to calculate?

For a Singapore employer, the monthly run for each employee covers:

  1. Gross pay: basic salary, allowances, overtime, deductions for unpaid leave.
  2. Wage type split: ordinary wages (monthly) and additional wages (bonuses, payouts).
  3. CPF: the employer share and the employee share, by age band and residency status.
  4. Other deductions and contributions: contributions to funds such as self-help groups where the employee opts in.
  5. Net pay, the payslip, the bank payment file and the CPF submission file.

Step 3 is where errors cluster. The CPF Board sets the rates by age and status, and they change. As an example, the CPF Board's contribution table shows that from 1 January 2026, for employees aged 55 and below with wages above S$750 a month who are Singapore Citizens or Singapore Permanent Residents from their third year, the employer pays 17% and the employee 20%, a total of 37% of wages. Other bands and statuses have other rates, and the page distinguishes ordinary wages from additional wages, each with its own ceiling.

How do we structure the CPF logic?

Three design choices keep it testable.

Rates live in data, not in code. A table keyed by year, age band and status holds each rate and ceiling, with an effective date. A rate change is a data change with a review, not a code deploy. The previous year's table stays, so a payslip regenerated for an earlier month uses the rates in force then.

Each rule is a pure function. Input: wage amounts, age on the pay date, status, year-to-date additional wages. Output: contribution amounts. No database calls, no clock, no hidden state. A pure function can be tested with a table of inputs and expected outputs.

Rounding is explicit. CPF contributions follow stated rounding rules, such as how the total is rounded and how the employee share is derived from it. We encode the rule once, name it, and test it. Rounding done differently in two places gives totals that differ by a dollar and a month of reconciliation work.

How do we test it?

We use four layers.

  1. Hand-computed cases. For each age band and status, a finance reviewer computes expected contributions on paper for a range of wages: below the threshold, at the threshold, mid-range, at the ceiling and above it. Those become fixed test cases. The expected values come from the published rules, not from our own code.
  2. Boundary cases. The day before and after an age change. The first month of a new rate year. A wage exactly at a ceiling. A bonus paid in a month where ordinary wages already hit the ceiling. Boundaries are where rules written from a summary break.
  3. Property checks. Employer plus employee equals total. Contributions never exceed the ceiling-derived maximum. Net pay equals gross minus deductions. Contributions are never negative. These hold for any input, so we run them against thousands of generated inputs.
  4. Parallel run. Before go-live, we run the engine beside the existing process for at least one cycle. Any difference is explained line by line. Either the old process had an error, or ours does. Both outcomes are findings.

The same four layers serve any rules engine. They are cheaper than they sound, because the pure functions need no setup.

What about mid-month joiners and leavers?

Proration is the second source of error. The rules vary: some employers prorate by calendar days, some by working days. Whichever your contract uses, it is a stated policy, held as a setting, and applied in one place. A joiner on the 17th produces a defined number of paid days, a defined basic pay and a CPF amount derived from that pay. We test joiners and leavers on every day of a 28-, 30- and 31-day month, because off-by-one errors only appear on specific days.

Who approves, and what is logged?

A payroll run moves money and files with a government body. So:

  • The run is drafted by the system and reviewed by a named person.
  • Changes to rates, salaries and bank details need a named approver and leave a log entry with the actor and time.
  • The payslip, bank file and CPF file are generated from the approved run, not recalculated afterwards.
  • Payroll access is restricted to a short allowlist of accounts. Employees see only their own payslip.

Filing and payment wait for a person. The system prepares them.

What do we run on our own books?

KYN runs its own payroll on 2026 CPF rules. The engine produces payslips, the bank file and the CPF file, and posts a manual journal to the accounting ledger. It is configured with an allowlist of users. We keep it as a reference build because we are the first client of any rule we get wrong.

What are the trade-offs?

  • Maintenance. Rates change each year, sometimes mid-year. Someone must own the update. In our model, this is part of the monthly retainer.
  • Scope. A custom engine pays off when you have unusual pay structures, several entities or a need to join payroll to other systems. For a ten-person company with plain salaries, a packaged payroll product may cost less. We would say so in the review.
  • Regulatory risk. The calculation is only as right as the rule reading. The parallel run and a sign-off by the accountant cover that.

Where KYN fits

KYN builds payroll and finance modules that run in a cloud account in your name, with row-level security in the database and every action logged with the actor. Money and filings wait for a named person. See finance and security.

The first 14 days are a review of your stack and your team's current process. A full build ships in under 90 days. Rights in the custom code and configuration pass to you on full payment.

Frequently asked questions

Can a payroll system calculate CPF automatically?

Yes. The rates are published by the CPF Board by age band and residency status. The risk is in edge cases such as ceilings, age changes and bonuses, which is why each rule needs boundary tests.

How do you know the payroll numbers are right?

We test against cases computed by hand from the published rules, check properties that must always hold, and run the new engine beside the old process for a full cycle. A named person approves the run before payslips go out.

What happens when CPF rates change?

Rates sit in a dated table, so a change is a reviewed data update. Earlier months keep the rates that applied then, which keeps regenerated payslips correct.

Checked 30 October 2026.

Curious whether Marketing agents fits your business? Talk to KYN on WhatsApp — no forms, just a conversation.

Start Building →

Written 29 Oct 2026 · Checked 29 Oct 2026