Turnover, with a denominator you can defend
Two dashboards, one month, two different turnover rates, and one of them says 200 percent. Nobody typed a wrong number. The reports disagree because each quietly chose a different denominator.
◆ The 200 percent reporta real artifact of endpoint arithmetic, reproduced in full.
Here is the failure practitioners keep rediscovering. A team has one person at the start of the month. That person leaves. The report computes the denominator as the average of the two endpoints: one at the start, zero at the end, so one half. One exit divided by one half is 200 percent turnover.
Every step is defensible in isolation and the result is nonsense. Endpoint averages collapse when the period is short, the team is small, or headcount moved sharply. The same arithmetic quietly bends larger numbers too; the small team just makes the bend visible.
| Endpoint math, one-person team | Value |
|---|---|
| Headcount at month start | 1 |
| Headcount at month end | 0 |
| Denominator, average of endpoints | 0.50 |
| Exits in the month | 1 |
| Reported turnover | 200.00 |
Beyond the denominator, two more distortions recur. Transfers processed as a termination plus a hire count as exits they are not, inflating the numerator. And after a reorganization, the delivered rollups follow today's hierarchy, so last year's rate for a renamed department becomes unanswerable. The movement model classifies transfers once; the trending store page covers the hierarchy problem. Sample values are illustrative, never client data.
◆ The calculation done rightdaily average denominators on the owned snapshot, worked in full.
The fix is a denominator with enough resolution to be honest: average headcount from the daily snapshot, here shown at month grain as the average of month-start and month-end. The population runs at 344 to 351 through the spring, the same population the labor cost report prices.
| Month, 2026 | Begin | End | Average | Exits | Monthly rate | Annualized |
|---|---|---|---|---|---|---|
| March | 344 | 347 | 345.50 | 3 | 0.87 | 10.42 |
| April | 347 | 350 | 348.50 | 2 | 0.57 | 6.89 |
| May | 350 | 351 | 350.50 | 4 | 1.14 | 13.69 |
| Quarter | 344 | 351 | 348.17 | 9 | 2.58 | 10.34 |
Rates are percentages: exits divided by the average, times one hundred, with annualized figures computed from the unrounded monthly rate. The quarter row averages the three monthly denominators and its 9 exits are the three months' sum, so every cell can be recomputed from its neighbors.
The battery that ties this catalog's money pages checks this table the same way. Rates travel with their counts, exactly as the turnover report prescribes. Sample values are illustrative, never client data.
-- monthly turnover: exits over average daily headcount, one population
WITH avg_hc AS (
SELECT DATE_TRUNC('month', snapshot_date) AS month,
AVG(daily_headcount) AS average_headcount
FROM (SELECT snapshot_date, COUNT(*) AS daily_headcount
FROM fct_worker_day WHERE is_active GROUP BY 1)
GROUP BY 1),
exits AS (
SELECT DATE_TRUNC('month', termination_date) AS month,
COUNT(*) AS exit_count
FROM fct_worker_event
WHERE event_type = 'termination' AND NOT is_transfer
GROUP BY 1)
SELECT a.month, e.exit_count, a.average_headcount,
ROUND(100.0 * e.exit_count / a.average_headcount, 2) AS monthly_rate
FROM avg_hc a
LEFT JOIN exits e ON e.month = a.month
ORDER BY a.month
The transfer filter on the exits table is where the movement classification earns its keep, and the daily average denominator is why the one-person team above computes as what it was: a small team losing its only member, not a 200 percent crisis.
- HR
- Human resources. Core HR is the module of record for people data.
- denominator
- The population a rate divides by. The choice that makes dashboards disagree.
- average headcount
- Headcount averaged across a period, here from daily snapshots.
- annualized
- A monthly or quarterly rate projected to a year. A projection, not a result.
- endpoint average
- Averaging only a period's first and last values. Cheap, and wrong when things move.
- transfer
- A move between organizations. Not an exit, unless the report mistakes it for one.
- snapshot
- A dated copy of a table's state, kept so the past stays queryable.
- crossfoot
- Recomputing a table's totals from its parts to prove they agree.