What is resolution rate, and how do you measure it in Metabase?
Resolution rate is the share of tickets that end resolved — solved tickets over all tickets that reached a terminal state, or over a created cohort if you want the demand-side view. Where resolution time measures speed, resolution rate measures whether the work actually got done. Measure it in Metabase from help desk data synced into a database (Zendesk, Gorgias, Front, or Freshdesk).
resolved ÷ closed-or-resolved per month, with reopened tickets excluded from the numerator. Watch the complement: every closed-unresolved ticket is an abandoned customer or an auto-close sweeping a problem under the rug.What resolution rate measures
It measures completion, and there are two honest ways to frame it:
- Closed-based — resolved ÷ all tickets that reached a terminal state in the period. Answers "of the tickets that left the queue, how many left it solved?" Stable immediately, good for weekly operations.
- Cohort-based — resolved ÷ tickets created in a period, measured after a maturity window. Answers "of the demand that arrived, how much did we eventually solve?" Slower to settle, harder to game.
The gap between the two is informative on its own: a closed-based rate far above the cohort rate means a growing pile of tickets that never reach any terminal state — a backlog problem hiding behind a good-looking percentage.
What data does resolution rate need?
- A tickets table with
status,solved_at, andclosed_at— and a sync that distinguishes "solved" from "closed without resolution." - A ticket events or audit table to detect reopens; without it, a solve-then-reopen-then-abandon ticket counts as resolved forever.
queue, category, or close-reason fields, so low rates can be traced to abandonment, auto-close policy, or unresolvable request types.
SQL patterns
A ticket counts as resolved only if no reopen event follows its solve.
-- Monthly resolution rate over closed tickets, counting a ticket as
-- resolved only if it was never reopened after its solve.
SELECT
date_trunc('month', t.closed_at) AS month,
COUNT(*) AS closed_tickets,
COUNT(*) FILTER (
WHERE t.status = 'solved'
AND NOT EXISTS (
SELECT 1
FROM ticket_events e
WHERE e.ticket_id = t.id
AND e.event = 'reopened'
AND e.created_at > t.solved_at
)
) AS resolved_clean,
ROUND(100.0 * COUNT(*) FILTER (
WHERE t.status = 'solved'
AND NOT EXISTS (
SELECT 1
FROM ticket_events e
WHERE e.ticket_id = t.id
AND e.event = 'reopened'
AND e.created_at > t.solved_at
)
) / NULLIF(COUNT(*), 0), 1) AS resolution_rate_pct
FROM tickets t
WHERE t.closed_at IS NOT NULL
GROUP BY date_trunc('month', t.closed_at)
ORDER BY month;Ranks queues by resolution rate to find where tickets end unresolved.
-- Resolution rate by category/queue, last 90 days of closed tickets.
-- Surfaces the queues where tickets end as abandoned or stale-closed.
SELECT
t.queue,
COUNT(*) AS closed_tickets,
COUNT(*) FILTER (WHERE t.status = 'solved') AS resolved,
COUNT(*) FILTER (WHERE t.status <> 'solved') AS closed_unresolved,
ROUND(100.0 * COUNT(*) FILTER (WHERE t.status = 'solved')
/ NULLIF(COUNT(*), 0), 1) AS resolution_rate_pct
FROM tickets t
WHERE t.closed_at >= current_date - INTERVAL '90 days'
GROUP BY t.queue
ORDER BY resolution_rate_pct ASC;Pitfalls
Where this metric applies
- Zendesk + Metabase — solved vs closed status plus audit events for reopens
- Gorgias + Metabase — ticket status and close events for e-commerce queues
- Front + Metabase — conversation resolution and reopen activity
- Freshdesk + Metabase — ticket status history and resolved timestamps