Metric · Support

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).

TL;DRresolved ÷ 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, and closed_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

Monthly resolution rate, reopens excludedPostgreSQL

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;
Resolution rate by queuePostgreSQL

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

Letting auto-close inflate the numerator.→ Many help desks mark stale tickets solved when they auto-close after inactivity. Count those as closed-unresolved (or track them separately) or your resolution rate measures your timeout policy, not your support.
Counting first solves that later reopen.→ A solve that comes back isn't a resolution. Exclude tickets with a subsequent reopen event, or use a settle window so the monthly number stops moving after a week.
Mixing the two denominators on one chart.→ Closed-based and cohort-based rates can differ by ten points on the same data. Pick one per card, label it, and never trend a series that switched definitions midway.
Reading a low rate as agent failure.→ Feature requests, spam, and duplicate tickets legitimately close unresolved. Segment by queue and close reason first — otherwise the fix becomes "close everything as solved," which is worse than the problem.

Where this metric applies

Metrics

Analytics & dashboards

FAQ

Resolution rate over closed tickets or over created tickets?
Both are legitimate, and they answer different questions. Resolved ÷ closed-or-resolved tells you how tickets end — what share leave the queue actually solved rather than abandoned or auto-closed. Resolved ÷ created, computed cohort-style on tickets opened in a period, tells you what fraction of incoming demand you eventually solve — but it needs a maturity window, because last week's cohort hasn't finished resolving yet. Pick the closed-based view for weekly operations and the cohort view for quarterly honesty checks, and label which one each card uses.
What's the difference between resolution rate and resolution time?
Resolution rate is whether tickets get solved; resolution time is how fast the solved ones got there. They fail independently: a team can resolve 98% of tickets slowly, or close tickets quickly by giving up on the hard ones. Resolution time only averages over tickets that made it to resolved, so it says nothing about the ones that didn't — which is exactly the population resolution rate exists to count.
How should reopened tickets be counted?
A reopened ticket wasn't resolved — it just looked that way for a while. The strict pattern is to count a ticket as resolved only if no reopen event follows its solve (or none within a fixed window, say 7 days, so the number eventually settles). If you can't exclude reopens, at least report reopen rate next to resolution rate; a 95% resolution rate with a 15% reopen rate is a very different story from the same rate at 2% reopens.
What does a low resolution rate actually indicate?
Usually one of three things: tickets abandoned by customers (often after long waits), auto-close policies sweeping stale tickets out unsolved, or genuine can't-fix categories like feature requests routed into support. Segment by queue and close reason before reacting — a low rate in a feature-request queue is triage working as intended, while a low rate in billing is a fire.
How do you track resolution rate in Metabase?
Sync your help desk into a SQL database with Airbyte, Fivetran, or a similar pipeline — Zendesk, Gorgias, Front, and Freshdesk all sync tickets with status and event history. Build the monthly trend with reopens excluded, add a by-queue breakdown, and pin both next to CSAT on the agent performance dashboard.