Metric · HR

What is cost per hire, and how do you measure it in Metabase?

Cost per hire is total recruiting spend — internal plus external — divided by hires in the period. It's the unit economics of recruiting: the number that turns "we spent a lot on agencies" into a per-hire figure you can compare across quarters, sources, and role families. Measure it in Metabase from ATS data synced from Greenhouse, Ashby, or BambooHR, joined to recruiting costs from your accounting system.

TL;DR(internal + external recruiting costs) ÷ hires, the SHRM formula. Define the numerator once and hold it; segment by source and role family, where 10x spreads live; and pair it with 90-day retention so the cheap source that can't keep its hires doesn't win the budget.

What does a cost per hire chart look like in Metabase?

Track blended cost per hire by quarter as a line and read the trend, not any single quarter. The gradual decline reflects a growing referral and inbound mix, while a spike like Q1 2025's usually traces to a few agency-sourced executive searches landing in one quarter — a mix shift, not a broken process.

Cost per hire in Metabase: a line chart of quarterly blended recruiting cost per hire.
Cost per hire as a Metabase card, built from ATS and accounting data. Figures are illustrative.

What cost per hire measures

It measures recruiting efficiency in currency. The SHRM-standard numerator has two halves: external costs — agency and search fees, job-board postings, background checks, assessment and sourcing tools — and internal costs — the share of recruiter and coordinator compensation attributable to hiring, plus referral bonuses. What you include is less important than including the same things every quarter; the metric's value is in the trend and the comparisons, and both die when scope drifts.

The blended average is a board slide. The working views are segmented: by source, where agency vs. referral vs. inbound routinely differ 10x; by role family and level, so an executive-heavy quarter doesn't read as inflation; and against a quality signal like 90-day retention, so optimizing cost never quietly optimizes for bad hires. Read it alongside time to hire — speed and cost are the trade-off pair.

What data does it need?

  • A hires model from your ATS with start_date, source (agency, referral, inbound, sourced), role family, and level — synced to your warehouse via Airbyte, Fivetran, or dlt.
  • A recruiting_costs table with amount, category (agency fees, job boards, tooling, recruiter comp, referral bonuses), and incurred_at — from your accounting export or a deliberately maintained sheet.
  • Per-hire cost allocations (direct fees tied to the hire; shared costs spread by convention) for the by-source view.
  • An early quality signal per hire — 90-day retention is the simplest — so cost never gets optimized in a vacuum.

SQL patterns

Quarterly cost per hire PostgreSQL
WITH quarterly_costs AS (
  SELECT
    date_trunc('quarter', incurred_at) AS quarter,
    SUM(amount) FILTER (
      WHERE category IN ('agency_fees', 'job_boards', 'tooling')
    ) AS external_costs,
    SUM(amount) FILTER (
      WHERE category IN ('recruiter_comp', 'referral_bonuses')
    ) AS internal_costs
  FROM recruiting_costs
  GROUP BY 1
),
quarterly_hires AS (
  SELECT
    date_trunc('quarter', start_date) AS quarter,
    COUNT(*) AS hires
  FROM modeled_hires
  GROUP BY 1
)
SELECT
  c.quarter,
  h.hires,
  c.external_costs,
  c.internal_costs,
  ROUND(
    (c.external_costs + c.internal_costs)
    / NULLIF(h.hires, 0), 0
  ) AS cost_per_hire
FROM quarterly_costs c
JOIN quarterly_hires h USING (quarter)
ORDER BY c.quarter;
Cost per hire vs. 90-day retention by source PostgreSQL
SELECT
  h.source,
  COUNT(*) AS hires,
  ROUND(
    SUM(a.allocated_cost) / NULLIF(COUNT(*), 0), 0
  ) AS cost_per_hire,
  ROUND(
    100.0 * COUNT(*) FILTER (WHERE h.retained_90d)
    / NULLIF(COUNT(*), 0), 1
  ) AS retained_90d_pct
FROM modeled_hires h
LEFT JOIN hire_cost_allocations a ON a.hire_id = h.id
WHERE h.start_date >= CURRENT_DATE - INTERVAL '12 months'
  AND h.start_date < CURRENT_DATE - INTERVAL '90 days'
GROUP BY 1
ORDER BY cost_per_hire DESC;

Pitfalls

Letting the numerator drift. → Adding employer branding one quarter and dropping tooling the next turns the trend into noise. Write the cost categories down, publish them next to the chart, and change them only with an annotation.
Reporting only the blended average. → Executive searches and volume hiring in one number cancel into mush. A quarter's average can rise because you hired more senior people — which is mix, not inefficiency. Segment by role family and level first.
Optimizing cost without a quality guardrail. → The cheapest source is sometimes cheap because its hires leave. Join cost per hire to 90-day retention (or another early quality-of-hire signal) before shifting budget toward the low number.
Forgetting internal costs entirely. → Counting only invoices makes inbound look free — but recruiter time is the biggest line for inbound-heavy teams. Allocate recruiter comp, even roughly, or the source comparison is fiction.

Where this metric applies

Metrics

Dashboards

FAQ

How is cost per hire calculated?
The SHRM standard: (internal recruiting costs + external recruiting costs) ÷ number of hires in the period. External covers agency fees, job-board postings, background checks, and recruiting tooling; internal covers recruiter compensation allocated to hiring and referral bonuses. The formula is trivial — the discipline is the scope. Write down what's in your numerator and hold it constant, because a quarter where someone quietly adds employer-branding spend is a quarter your trend stops meaning anything.
What's a typical cost per hire?
Averages around a few thousand dollars per hire get quoted, but the spread is enormous: an inbound applicant for a junior role and an agency-sourced executive differ by more than an order of magnitude. That's why the blended number is nearly useless on its own — segment by role family, level, and source before comparing anything. The by-source view is the actionable one: agency vs. referral vs. inbound routinely differ 10x, which is a budget-allocation argument sitting in a chart. Pair it with source quality.
Should cheap sources win the recruiting budget?
Only if their hires stay and perform. A source that delivers at a third of the cost but half the 90-day retention is more expensive per retained hire — you pay again in backfill, and first-year turnover eats the savings. That's why the second query joins cost per hire to 90-day retention by source: cost-only optimization quietly selects for the sources that produce departures.
How does cost per hire relate to time to hire?
They're the two axes of recruiting efficiency, and they trade off. Agencies compress time to hire at a steep cost premium; inbound pipelines are cheap but slow to build. An open role has its own carrying cost in lost output, so the cheapest process on paper isn't always cheapest in practice. Review the pair together — with time to fill for the requisition view — before concluding a channel is expensive.
How do you track cost per hire in Metabase?
Two feeds into one SQL database: hires from your ATS — Greenhouse, Ashby, or BambooHR — synced via Airbyte, Fivetran, or dlt, and recruiting costs from your accounting system or a maintained cost sheet, categorized and dated. Metabase queries the database, not the tools' APIs. Model quarterly costs and hires, divide, then break out the by-source view with retention and pin both to a hiring plan dashboard.