Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

IT Support & Help Desk Fundamentals  Module 12 – Service desk practice

Tickets, priority and SLAs that hold up

Walk a ticket through its states, set priority from a 3x3 matrix, compute an SLA deadline across time zones and holidays, and spot metrics that can be gamed.

  • Beginner
  • 20 minutes
  • Examples run with Python 3.14.8 and Pyodide 314.0.7
  • By MySmartCoPilot
Free lesson, Pro answers: 20 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Move a ticket through its states correctly, from new to closed, reopening a related ticket instead of a duplicate
  • Set priority from impact and urgency with a published matrix
  • Calculate an SLA deadline in business hours across time zones and holidays
  • Read service-desk metrics and show how they can be gamed

Before you start

What you’ll learn · Before you start

What you will learn

  • Move a ticket through its states correctly, from new to closed, reopening a related ticket instead of a duplicate
  • Set priority from impact and urgency with a published matrix
  • Calculate an SLA deadline in business hours across time zones and holidays
  • Read service-desk metrics and show how they can be gamed

Before you start

On this page

A help desk works 09:00 to 18:00 IST, Monday to Friday. A ticket: The record of one support request: who it is for, the problem, every action taken with its time, and how it was resolved. The service desk works and hands on tickets, and closes one when the problem is fixed. More in “Ticket notes and handoffs people can use” with a 60-minute resolution target lands at 17:30 on a Thursday, and the Friday is a published holiday. Added on a wall clock, the 60 minutes end at 18:30 that evening, so the ticket breaches while nobody is at the desk; counted in business minutes against the holiday calendar, the same promise ends on Monday at 09:30.

Tickets, priority and SLAs hold up when each fault keeps one ticket with its whole history, priority is read off a matrix the organisation has published, the SLA clock counts only the desk’s open minutes, a customer’s time is converted to the desk’s clock before any minute is added, and the desk’s metrics are read together so no single number can be gamed. Each ticket is written as the ticket notes and handoffs lesson showed, with the exact error text and an action log: The time-ordered list of what was done on a ticket: one action per line, each with its result and a timestamp that carries a UTC offset, so any shift can follow what happened and when. More in “Ticket notes and handoffs people can use” whose entries carry a UTC offset.

A ticket moves through six states, and a returning fault reopens it

A ticket is not a flat note; it moves. Its six states are new, assigned, in progress, pending, resolved and closed. New means the request has arrived and nobody owns it; assigned means a triager or a routing rule has given it an owner; in progress means the owner is working on it; pending means the owner is waiting on a reply, usually from the user or a vendor; resolved means the fix is in and the user has been told; and closed means an idle window has passed with no objection. The pending state: The state a ticket moves to while the owner is waiting on a reply, usually from the user or a vendor. The service-level agreement clock pauses while a ticket is pending only if the agreement itself names that rule. pauses the service-level agreement: A written contract between the service desk and its users or customers, naming the targets the desk commits to for each priority (response time, resolution time) and the business hours and holidays those targets are measured against. Its short name is SLA. clock only when the agreement itself says so, which is why the words of the agreement matter as much as the states.

Step through one ticket from the first call to the closed window, and watch the last step, where the same fault comes back after the ticket has closed:

Interactive · step by step The six ticket states, and the reopen arrow Follow one ticket through its states, then watch what happens when the same fault returns the next day.
The six ticket states, and the reopen arrow, step 6 of 6. Showing new, assigned, pending (clock may pause), in progress, resolved (fix landed), closed (same fault returns). In focus: closed, in progress.pickstartwait / replyfixwindow endsreopennewjust arrivedassignedowner pickedpendingclock may pausein progresswork in handresolvedfix landedclosedsame fault returnsreopen

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. A new request lands. A user calls, writes or opens a portal form, and the record is created with the description and the start time. Nobody owns it yet, so the state is new.
  2. An owner picks it up. A triager or a routing rule gives the ticket an owner, and its state becomes assigned. The clock the agreement sets started at the request time, not now.
  3. The work starts. The owner begins the diagnosis and logs each action. The state is in progress. The response-target clock, if one applies, stops when the first substantial reply reaches the user.
  4. Waiting on a reply. The owner needs a reply from the user or a vendor to go further, so the state moves to pending. The resolution clock pauses only if the agreement says a pending state pauses it, so read before you promise.
  5. Fix landed, window closes. The reply arrives, the fix is delivered, and the state becomes resolved. After an idle window the user has to object in, the ticket closes with the resolution note that explains what the fix was.
  6. The fault returns, reopen. The user hits the same error the next morning. Reopen the related ticket rather than open a fresh one, so the history travels with the work and metrics stay honest. The state goes back to in progress.

The arrow back from closed is the one most new analysts miss. When the same fault returns, reopen the related ticket rather than open a fresh one. The history travels with the work, the next technician reads what was already tried, and the clock keeps the minutes already spent. A duplicate loses the history, counts the second contact as first-contact resolution and makes the fault look rarer than it is. A fresh ticket is right for a different fault on the same device, and a symptom alone does not always tell the two apart, so compare the exact error text with the earlier ticket before you choose.

A fresh ticket for a returning fault

Wrong: a VIP marks a ticket closed on their own, hits the same error ten minutes later, and the analyst opens a new one that resolves at first contact. Right: reopen the related ticket, keep the time already on the clock, and record the second contact in the same thread. The second route is slower today and honest in every metric.

Checkpoint

Check: States and the reopen arrow

  1. Question 1 of 2 Which order moves a ticket from arrival to the window closing?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: new -> assigned -> in progress -> pending -> resolved -> closed

    Six states in order: new (just arrived), assigned (owner picked), in progress (work in hand), pending (waiting on a reply), resolved (fix delivered) and closed (window ended with no objection).

  2. Question 2 of 2 A user hits the same error ten minutes after a ticket closed. What do you do?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Reopen the related ticket so the state moves from closed back to in progress

    Reopen moves the state from closed back to in progress and keeps the earlier error text, action log and notes with the work. A duplicate is right only for a different fault on the same device, which the symptom alone does not show.

Priority is impact and urgency, read off a published matrix

Priority answers one question: which ticket is worked next. It is not how the caller feels, and it is not first come, first served. The two inputs are impact: In service-desk work: how many people a fault affects and how critical the service it stops is. One axis of the priority matrix: low, medium or high., how many people a fault affects or how critical the service is, and urgency: In service-desk work: how fast the harm from a fault grows if it is left in place. The other axis of the priority matrix: low (no deadline), medium (today) or high (minutes to harm)., how fast the harm grows if the fault is left in place. Each is read on three steps (low, medium, high), so the priority matrix: A 3x3 table that reads impact against urgency and prints the priority band (such as P1 to P4) for each cell. Every organisation publishes its own matrix in its service-level agreement. has nine cells and four priority bands. Each organisation sets its own matrix and the targets of each band in its SLA; CompTIA’s A+ Core 2 objectives name severity and escalation levels among the parts of a ticketing system, and list service-level agreements among the documents a support technician works with. The table below is the sample MySmartCoPilot uses in this lesson; at work, read your own organisation’s matrix.

Urgency (rows) by impact (columns) Low: one user Medium: a team High: a site or a critical service
Low: no deadline P4 P3 P2
Medium: today P3 P2 P2
High: minutes to harm P2 P2 P1

Find a ticket’s row and its column, and the cell is its priority. Two tickets show how. A VIP’s forgotten password is low impact (one user) and medium urgency (mail still works on their phone, so the harm grows through the day, not by the minute), so it is P3. The stopped payroll server is high impact (a critical service for the whole organisation) and high urgency (the payroll team cannot work, and every minute comes out of the time left before tomorrow’s pay run), so it is P1. P1 goes first even if the VIP called first, and the VIP gets a short message that says what you are doing and when the next update will come. When a priority does have to change, the change and its reason are written in the ticket.

Key idea

Priority comes from two readings, impact and urgency, looked up on a matrix the organisation has already written. A change of priority is a decision with its reason in the ticket, not a judgement about the caller.

Checkpoint

Check: Priority from a published matrix

  1. Question 1 of 2 In the lesson matrix, what is the priority of a fault with high impact (a whole site) and high urgency (minutes to harm)?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: P1

    The matrix pairs three impact steps with three urgency steps. High impact and high urgency sit in the top-right cell and read P1 on this lesson's sample matrix.

  2. Question 2 of 2 At the same minute, a VIP needs a password reset (low impact, medium urgency) and the shared payroll server stopped (high impact, high urgency). Which wins?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The payroll server, because P1 beats P3

    The matrix reads the VIP password at P3 (low impact, medium urgency) and the payroll outage at P1 (high, high). P1 wins against P3, and the VIP gets a short message with the next update time.

An SLA clock counts only business minutes, and holidays count none

A service-level agreement commits the desk to two clocks for each priority. The response target: How soon, in business hours, a service-level agreement commits a human reply to the user after a ticket of a given priority is raised. The response clock stops at the first substantial reply. is how soon the user hears from a person; the resolution target: How soon, in business hours, a service-level agreement commits the fault to be fixed for a ticket of a given priority. Measured against the business-hours calendar and the holiday calendar for the office. is how soon the fault is fixed. Both are measured in business hours, against the published business-hours calendar: The published daily working hours of a service desk, such as 09:00 to 18:00 Monday to Friday. Service-level agreement clocks count minutes only inside these windows, so a wall-clock promise is replaced with a business-hours one. (here 09:00 to 18:00, Monday to Friday) and the office’s holiday calendar: The list of dates on which an office is closed and no business minutes elapse, such as a country's public holidays or an organisation's shutdowns. The service-level agreement reads it beside the business hours.. A promise in wall-clock hours runs on through nights, weekends and holidays, when nobody is working the ticket; a promise in business hours counts only the minutes the desk is open. The MySmartCoPilot public holidays tool lists India’s Central Government holidays, US federal holidays and UK bank holidays when you need a real calendar.

Take case 1 of the program below. The request lands at 17:30+05:30 on a Thursday and the P2 resolution target is 60 business minutes. The Friday is a holiday on the desk’s calendar, so the clock has to carry 30 of its 60 minutes across the holiday and the weekend to Monday. Follow it phase by phase:

Timeline · 6 events in order Adding 60 business minutes across a holiday Follow the clock from the first call to the deadline. Every phase names what the hour costs the clock, so the Monday morning deadline is a sum, not a guess.
  1. 17:30+05:30

    Request lands at 17:30 on a Thursday start

    The user reports the fault 30 minutes before close. The desk promises a 60-business-minute resolution, so the agreement clock begins at this moment on the IST business calendar.

  2. 18:00+05:30

    Close takes the first 30 minutes in progress

    The desk closes at 18:00. Thirty of the sixty minutes have been spent inside Thursday business hours, so 30 minutes are left to spend on a later working day.

  3. Friday is off

    The published holiday counts nothing paused

    The Friday is a sample holiday on this desk, and the holiday calendar says it is not a working day. Zero business minutes elapse on it, and the clock does not advance.

  4. Weekend is off

    Saturday and Sunday count nothing paused

    Saturday and Sunday are not working days, so no business minute is spent on either of them. The clock stays at 30 minutes to go into Monday.

  5. 09:00+05:30

    Monday open resumes the clock in progress

    The desk opens on Monday at 09:00 and the clock resumes with 30 business minutes still to spend. Every minute from here counts.

  6. 09:30+05:30

    Deadline lands on Monday 09:30 deadline

    Thirty minutes after open, the clock has spent the second half of the hour. The resolution deadline is Monday 09:30+05:30, four calendar days after the request but 60 business minutes after it.

The timeline has 6 events, from 17:30+05:30 to 09:30+05:30.

The program does the same sum in Python, so the timeline and its output agree. Cases 2, 3 and 4 add three awkward starts: a Saturday, a time written in UTC and a time before the desk opens.

Four SLA cases, with weekends, a holiday and a UTC input Python · sla/sla.py
"""Add business minutes across holidays and time zones for one service desk.

Every moment below is invented. The desk runs 09:00-18:00 India Standard Time
(IST), Monday to Friday, and a sample holiday falls on Friday 2026-10-02. The
IANA tz database file for Asia/Kolkata gives IST a constant +05:30 offset, so
Pyodide (which has no zoneinfo) can model it with datetime.timezone and the
times carry a UTC offset the way RFC 3339 asks.
"""

from datetime import date, datetime, time, timedelta, timezone

IST = timezone(timedelta(hours=5, minutes=30))   # Asia/Kolkata, +05:30
UTC = timezone.utc

DEFAULT_HOURS = (time(9, 0), time(18, 0))        # 09:00 to 18:00 local


def add_business_minutes(start, minutes, holidays=(), hours=DEFAULT_HOURS):
    """Return the moment that is `minutes` business minutes after `start`.

    - `start` is an aware datetime. If it is not already in IST, it is read as
      an IST clock first, so the business hours belong to the desk.
    - `hours` is an (open, close) pair of local times; the default is 09:00
      to 18:00, nine working hours a day.
    - Days off: Saturday, Sunday, and any date in `holidays`.
    - If the start sits before opening, the clock starts at the day's open.
      If at or after close, or on a weekend or holiday, the clock rolls to
      the next working day's open before any minutes are added.
    """
    if start.tzinfo is None:
        raise ValueError("start must be timezone-aware")
    cursor = start.astimezone(IST)
    open_t, close_t = hours
    remaining = timedelta(minutes=minutes)
    off_days = set(holidays)
    while True:
        day = cursor.date()
        day_open = datetime.combine(day, open_t, tzinfo=IST)
        day_close = datetime.combine(day, close_t, tzinfo=IST)
        if cursor.weekday() >= 5 or day in off_days or cursor >= day_close:
            cursor = datetime.combine(day + timedelta(days=1), open_t, tzinfo=IST)
            continue
        if cursor < day_open:
            cursor = day_open
        left_today = day_close - cursor
        if remaining <= left_today:
            return cursor + remaining
        remaining -= left_today
        cursor = datetime.combine(day + timedelta(days=1), open_t, tzinfo=IST)


def iso(when):
    """ISO 8601 to the minute, with the colon offset: 2026-10-05T09:30+05:30."""
    return when.isoformat(timespec="minutes")


WEEKDAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]


def day_name(when):
    return WEEKDAYS[when.weekday()]


# Case 1: Thursday evening, Friday is a published holiday, +60 business minutes.
holiday = {date(2026, 10, 2)}
case1_start = datetime(2026, 10, 1, 17, 30, tzinfo=IST)
case1_end = add_business_minutes(case1_start, 60, holidays=holiday)
print("Case 1 - Thursday 17:30 with Friday 2026-10-02 as a holiday, +60 min:")
print(f"    start:    {iso(case1_start)}   ({day_name(case1_start)})")
print(f"    deadline: {iso(case1_end)}   ({day_name(case1_end)})")
print()

# Case 2: a start on a Saturday rolls forward to Monday's open.
case2_start = datetime(2026, 10, 10, 10, 0, tzinfo=IST)
case2_end = add_business_minutes(case2_start, 60)
print("Case 2 - Saturday morning, +60 min (no extra holiday):")
print(f"    start:    {iso(case2_start)}   ({day_name(case2_start)})")
print(f"    deadline: {iso(case2_end)}   ({day_name(case2_end)})")
print()

# Case 3: a UTC input is converted to the IST business clock first.
case3_start = datetime(2026, 10, 7, 10, 0, tzinfo=UTC)
case3_end = add_business_minutes(case3_start, 45)
print("Case 3 - a UTC input, read on the IST clock first, +45 min:")
print(f"    start (UTC): {iso(case3_start)}   ({day_name(case3_start)})")
print(f"    start (IST): {iso(case3_start.astimezone(IST))}")
print(f"    deadline:    {iso(case3_end)}   ({iso(case3_end.astimezone(UTC))} UTC)")
print()

# Case 4: a start before opening on the same day uses the day's open.
case4_start = datetime(2026, 10, 12, 7, 15, tzinfo=IST)
case4_end = add_business_minutes(case4_start, 90)
print("Case 4 - Monday 07:15 (before the desk opens), +90 min:")
print(f"    start:    {iso(case4_start)}   ({day_name(case4_start)})")
print(f"    deadline: {iso(case4_end)}   ({day_name(case4_end)})")

Output

Case 1 - Thursday 17:30 with Friday 2026-10-02 as a holiday, +60 min:
    start:    2026-10-01T17:30+05:30   (Thursday)
    deadline: 2026-10-05T09:30+05:30   (Monday)

Case 2 - Saturday morning, +60 min (no extra holiday):
    start:    2026-10-10T10:00+05:30   (Saturday)
    deadline: 2026-10-12T10:00+05:30   (Monday)

Case 3 - a UTC input, read on the IST clock first, +45 min:
    start (UTC): 2026-10-07T10:00+00:00   (Wednesday)
    start (IST): 2026-10-07T15:30+05:30
    deadline:    2026-10-07T16:15+05:30   (2026-10-07T10:45+00:00 UTC)

Case 4 - Monday 07:15 (before the desk opens), +90 min:
    start:    2026-10-12T07:15+05:30   (Monday)
    deadline: 2026-10-12T10:30+05:30   (Monday)

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 sla.py

Case 2 starts on a Saturday, so nothing counts until Monday’s 09:00 open and the 60 minutes end at 10:00. Case 3’s 10:00 UTC is 15:30 on the desk’s clock, and 45 minutes later is 16:15+05:30, which the program also prints as 10:45 UTC. Case 4 starts at 07:15, before opening, so its 90 minutes run from 09:00 and end at 10:30, 195 minutes after the start on the wall clock.

The wall-clock promise

Wrong: “resolve in 4 hours”, carried straight to the ticket. Right: “resolve in 4 business hours on the published 09:00 to 18:00 schedule, with every holiday on the office calendar counting zero minutes”. The first slips every evening; the second lands on a working minute.

Checkpoint

Check: SLA clocks in business hours

  1. Question 1 of 2 An SLA promises resolution in four hours. On the lesson desk, four hours of what?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Four business hours against the published 09:00 to 18:00 schedule, with the holiday calendar

    The agreement names business hours, measured against the published hours and the holiday calendar. The MySmartCoPilot public holidays tool lists India's Central Government holidays, US federal holidays and UK bank holidays when a real calendar is needed.

  2. Question 2 of 2 In sla.py Case 1 (Thursday 17:30 start, +60 minutes, the Friday a holiday), how many of the 60 business minutes still have to be spent after the Monday open?

    Type a number.

    A hint

    Work out first how many minutes lie between 17:30 and the Thursday close.

    Show the answer: Question 2 of 2

    Answer: 30 minutes

    Thursday 17:30 to 18:00 spends 30 minutes. Friday is a holiday, Saturday and Sunday are not working days, so none of them count. The remaining 30 minutes are spent on Monday starting at 09:00, which is why the deadline lands at 09:30+05:30.

Convert a customer’s time to the desk’s clock before adding minutes

India Standard Time is a fixed offset of +05:30: the IANA tz database’s asia file gives Asia/Kolkata that offset with no daylight saving since 1945. Many customers do not live on a fixed offset. The United Kingdom moves between Greenwich Mean Time (+00:00) and British Summer Time (+01:00) on the last Sundays of March and October, and most of the United States moves on dates of its own in March and November, as the tz database’s europe and northamerica files record. A deadline promised to such a customer needs a time-zone library that knows those rules, not an offset typed in once, which is right for only part of the year. The timestamp converter and the timezone converter do the same conversion by hand when you read a ticket from another clock.

Follow one UK customer’s time through the steps below; the dashed arrow back is the ticket whose time has no offset:

Interactive · stage by stage Convert before you promise Walk one UK customer's time through the five steps to a deadline on the desk's clock. The dashed arrow back is the ticket whose time has no offset.
Convert before you promise, step 5 of 5. Showing Receive the time, Pin its offset, Convert to IST, Add business minutes, Write the deadline. In focus: Write the deadline.no offset: askReceive the timeexactly as writtenPin its offsetor from the cityConvert to ISTthe desk's clockAdd business minutesskip closed hoursWrite the deadlineon both clocks

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. Receive the time as written. A UK customer reports a fault at Monday 20:30+01:00. Keep the time exactly as the customer wrote it, offset included, because the offset says which moment they mean.
  2. Pin the offset, or ask. The offset is +01:00, and the UK keeps British Summer Time (+01:00) from the last Sunday of March to the last Sunday of October, so it fits the date. A time with no offset and no city names no single moment: ask the user, and start again when they reply.
  3. Convert to the desk's clock. The desk works on India Standard Time, which the IANA tz database gives Asia/Kolkata as +05:30 all year. 20:30+01:00 is 19:30 UTC, which is 01:00+05:30 on Tuesday on the desk clock.
  4. Count the business minutes. 01:00 is before the desk opens, so no minute counts until 09:00. A four-business-hour promise then ends at 13:00+05:30 on Tuesday, well inside the 09:00 to 18:00 day.
  5. Write the deadline twice. Give the customer the deadline on their own clock: 13:00+05:30 is 07:30 UTC, which is 08:30+01:00 in the UK. Keep both forms in the ticket, so whoever picks it up next reads the same moment.

The order matters: pin the offset, convert to the desk’s clock, add the SLA minutes across business hours and holidays, then write the deadline on the customer’s own clock as well, so they can plan. A time with no offset is a problem the desk cannot solve on its own. “I called at 20:30” names no single moment: 20:30 in Kolkata, in London and in New York are three instants, hours apart. Ask for the city or the offset before you promise a deadline. That is also why the ticket notes lesson writes every action-log entry as an ISO 8601 timestamp: A date and time written in the international ISO 8601 order, from the largest unit to the smallest, with a UTC offset after the time, as in a time written 14:05+05:30, or a trailing Z for UTC. More in “Ticket notes and handoffs people can use” with its offset; RFC 3339, the internet profile of ISO 8601, makes the offset, or a Z for UTC, part of every timestamp.

Key idea

Convert the time to the desk’s clock before you add minutes to it. A customer’s time without an offset is a question, not a start.

Checkpoint

Check: Offsets and daylight saving

  1. Question 1 of 2 A desk in India writes its times as 17:30+05:30. A customer in the UK writes 20:30+01:00 in summer. Which clock moves twice a year, and which does not?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: The UK clock moves; India is on a constant +05:30.

    Pin a time with the offset that was in force at the moment it names, not with a hard-coded guess. A time-zone library reads the right offset from the tz database for each date.

  2. Question 2 of 2 A ticket from a new customer opens with "I called at 20:30" and nothing else. What is your next move?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Ask for the city or the offset before promising a deadline

    A time with no offset is a question, not a start. Convert to the desk's clock with a time-zone library only after the user names the city or the offset, so the SLA minutes land on the right moment.

Each desk metric can be gamed, so read them together

Service-desk metrics are easy to compute and easy to game. Four that a desk is judged on: first-contact resolution: The share of closed tickets that were resolved during the first contact with the user, with no later work needed. Written FCR. Easy to flatter by splitting one ticket into two or by closing early. (the share of closed tickets resolved during the first contact), mean time to resolve: The average time between a ticket's creation and its resolution, taken over the closed tickets in a window. Written MTTR. Falls alongside a rising reopen rate when tickets are being closed too soon. (how long a ticket takes on average, from creation to resolution), backlog age: The average age of the tickets that are still open at the moment the report is run. Measured in hours or days; it moves only when tickets are opened, closed or stay open longer, not when a closed ticket is split. (how old the open tickets are on average) and the reopen rate: The share of closed tickets that had to be reopened within a window, usually a few days. A rising reopen rate beside a falling mean time to resolve is the signature of a desk closing tickets too early. (the share of closed tickets that had to be reopened). A fifth, satisfaction, needs the user and is outside this short example.

Each one has a trick that lifts the number without a better outcome for the user. The example reads an invented week of 15 tickets and prints the four numbers. Then it splits T-02, a ticket that was not resolved at first contact, into two tickets that are both marked as resolved at first contact, and prints them again:

One week of tickets, before and after a ticket is split Python · metrics/metrics.py
"""Read a week of invented tickets and show four service-desk metrics on them,
then show how splitting one ticket into two inflates first-contact resolution
without any change for the user.

All ticket data is invented. The fixed "now" the report uses is
2026-10-19T18:00+05:30, so backlog age is deterministic. The clock is a fixed
+05:30 offset (Asia/Kolkata, from the IANA tz database) because Pyodide, the
browser Python runtime, has no zoneinfo.
"""

from datetime import datetime, timedelta, timezone

IST = timezone(timedelta(hours=5, minutes=30))                  # +05:30
NOW = datetime(2026, 10, 19, 18, 0, tzinfo=IST)                 # the fixed "now"

# One row per ticket: (id, created, resolved | None, resolved on first contact, reopens).
TICKETS = [
    ("T-01", datetime(2026, 10, 12,  9, 30, tzinfo=IST), datetime(2026, 10, 12, 10,  5, tzinfo=IST), True,  0),
    ("T-02", datetime(2026, 10, 12, 10,  0, tzinfo=IST), datetime(2026, 10, 13, 12, 45, tzinfo=IST), False, 0),
    ("T-03", datetime(2026, 10, 12, 11, 15, tzinfo=IST), datetime(2026, 10, 12, 11, 40, tzinfo=IST), True,  0),
    ("T-04", datetime(2026, 10, 13,  9, 10, tzinfo=IST), datetime(2026, 10, 13, 10,  0, tzinfo=IST), True,  1),
    ("T-05", datetime(2026, 10, 13, 11,  0, tzinfo=IST), datetime(2026, 10, 14, 15, 20, tzinfo=IST), False, 0),
    ("T-06", datetime(2026, 10, 14, 10, 45, tzinfo=IST), datetime(2026, 10, 14, 11, 10, tzinfo=IST), True,  0),
    ("T-07", datetime(2026, 10, 14, 14,  0, tzinfo=IST), datetime(2026, 10, 15,  9, 45, tzinfo=IST), False, 0),
    ("T-08", datetime(2026, 10, 15,  9, 20, tzinfo=IST), datetime(2026, 10, 15, 10,  0, tzinfo=IST), True,  0),
    ("T-09", datetime(2026, 10, 15, 11, 30, tzinfo=IST), datetime(2026, 10, 16, 10, 10, tzinfo=IST), False, 1),
    ("T-10", datetime(2026, 10, 15, 15, 10, tzinfo=IST), datetime(2026, 10, 15, 16,  0, tzinfo=IST), True,  0),
    ("T-11", datetime(2026, 10, 16,  9,  0, tzinfo=IST), datetime(2026, 10, 16, 11, 30, tzinfo=IST), True,  0),
    ("T-12", datetime(2026, 10, 16, 14, 20, tzinfo=IST), None,                                       False, 0),
    ("T-13", datetime(2026, 10, 16, 16,  0, tzinfo=IST), None,                                       False, 0),
    ("T-14", datetime(2026, 10, 19,  9, 10, tzinfo=IST), datetime(2026, 10, 19,  9, 55, tzinfo=IST), True,  0),
    ("T-15", datetime(2026, 10, 19, 11,  0, tzinfo=IST), None,                                       False, 0),
]


def closed(tickets):
    return [t for t in tickets if t[2] is not None]


def still_open(tickets):
    return [t for t in tickets if t[2] is None]


def first_contact_resolution(tickets):
    done = closed(tickets)
    if not done:
        return 0.0
    hits = sum(1 for t in done if t[3])
    return 100 * hits / len(done)


def mean_time_to_resolve(tickets):
    done = closed(tickets)
    if not done:
        return timedelta(0)
    total = sum((t[2] - t[1] for t in done), timedelta())
    return total / len(done)


def backlog_age(tickets, now):
    opened = still_open(tickets)
    if not opened:
        return timedelta(0)
    total = sum((now - t[1] for t in opened), timedelta())
    return total / len(opened)


def reopen_rate(tickets):
    done = closed(tickets)
    if not done:
        return 0.0
    hits = sum(1 for t in done if t[4] > 0)
    return 100 * hits / len(done)


def hhmm(td):
    """Hours and minutes form of a timedelta: 8:42."""
    total = int(td.total_seconds())
    hours, rest = divmod(total, 3600)
    minutes = rest // 60
    return f"{hours}:{minutes:02d}"


def report(label, tickets):
    print(f"{label}:")
    print(f"    tickets:        {len(tickets)} ({len(closed(tickets))} closed, {len(still_open(tickets))} open)")
    print(f"    FCR:            {first_contact_resolution(tickets):.1f} %")
    print(f"    MTTR:           {hhmm(mean_time_to_resolve(tickets))}  (hours:minutes)")
    print(f"    reopen rate:    {reopen_rate(tickets):.1f} %")
    print(f"    backlog age:    {hhmm(backlog_age(tickets, NOW))}  (hours:minutes)")
    print()


report("Service-desk week, as recorded", TICKETS)

# Game: split T-02 into T-02a and T-02b, both "resolved on first contact".
# Nothing changes for the user; the second ticket wraps up with the same
# resolution a day later. FCR, MTTR and the reopen rate all move; only the
# ticket count (16 tickets for the same 15 problems) gives the split away.
original = next(t for t in TICKETS if t[0] == "T-02")
gamed = []
for t in TICKETS:
    if t[0] == "T-02":
        gamed.append(("T-02a", original[1],                         original[1] + timedelta(minutes=20), True, 0))
        gamed.append(("T-02b", original[1] + timedelta(minutes=25), original[2],                        True, 0))
    else:
        gamed.append(t)

report("Same week, with T-02 split into T-02a and T-02b (both 'first contact')", gamed)

base_fcr = first_contact_resolution(TICKETS)
gamed_fcr = first_contact_resolution(gamed)
base_mttr = mean_time_to_resolve(TICKETS)
gamed_mttr = mean_time_to_resolve(gamed)
delta_fcr = gamed_fcr - base_fcr
print(f"FCR moved from {base_fcr:.1f} % to {gamed_fcr:.1f} % (up {delta_fcr:.1f} points).")
print(f"MTTR moved from {hhmm(base_mttr)} to {hhmm(gamed_mttr)} (hours:minutes).")
print("The user got nothing different; three of the four numbers now look better.")

Output

Service-desk week, as recorded:
    tickets:        15 (12 closed, 3 open)
    FCR:            66.7 %
    MTTR:           8:42  (hours:minutes)
    reopen rate:    16.7 %
    backlog age:    52:13  (hours:minutes)

Same week, with T-02 split into T-02a and T-02b (both 'first contact'):
    tickets:        16 (13 closed, 3 open)
    FCR:            76.9 %
    MTTR:           8:01  (hours:minutes)
    reopen rate:    15.4 %
    backlog age:    52:13  (hours:minutes)

FCR moved from 66.7 % to 76.9 % (up 10.3 points).
MTTR moved from 8:42 to 8:01 (hours:minutes).
The user got nothing different; three of the four numbers now look better.

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 metrics.py

First-contact resolution rose from 66.7 to 76.9 per cent and mean time to resolve fell from 8:42 to 8:01 (hours and minutes). The reopen rate slipped from 16.7 to 15.4 per cent too, because the split added one closed ticket and no reopen. Backlog age stayed at 52:13, because no open ticket moved. Three of the four numbers look better, and the user is in the same position as before. The one line that gives the split away is the count: 16 tickets for the same 15 problems. Closing a ticket too early is the other common pull: mean time to resolve drops because the fix never had to land, and the reopen rate climbs when the fault comes back. Read the metrics together and beside the ticket count. A falling mean time to resolve beside a rising reopen rate is a desk closing too soon, not a desk working fast.

Reading the dashboard, not the user

Wrong: “first-contact resolution is up ten points this week, keep doing what you did”. Right: compare the same weeks on reopen rate, backlog age and the number of tickets for each problem reported. If the reopen rate rose, or the tickets grew faster than the problems, the gain is in the bookkeeping, not in the service.

Checkpoint

Check: Reading metrics together

  1. Question 1 of 2 In metrics.py, which numbers moved after T-02 was split into T-02a and T-02b? Choose every one.

    Choose every answer that is right.

    Show the answer: Question 1 of 2

    Answer:

    • The reopen rate, which fell
    • First-contact resolution, which rose
    • Mean time to resolve, which fell

    Splitting is a bookkeeping move. Every number that is counted over closed tickets moved, three of the four, while the user got nothing more. Only the ticket count, 16 tickets for the same 15 problems, shows what happened.

  2. Question 2 of 2 A dashboard shows mean time to resolve falling fast and reopen rate rising at the same time. What does the pair most likely mean?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The desk is closing tickets too early, so the clock stops but the fault returns

    Service-desk metrics are gameable one at a time, so read them together. Mean time to resolve and reopen rate move in opposite directions when tickets close too soon, which the dashboard would otherwise call a win.

Practise: a desk that also opens on Saturday mornings

The program in this lesson closes its desk at weekends. The exercise moves to a desk whose published week adds Saturday from 09:00 to 13:00, and asks you to write add_business_minutes for that week, with holidays, a UTC input and a different week passed in as an argument. Its sample tests start on a Friday evening, on a Saturday before and after its early close, on a Sunday and before opening, so a copy of the lesson’s function fails several of them.

Exercise · Medium · Python

Count business minutes for a desk that opens on Saturday mornings

The lesson's desk is closed at weekends. This desk publishes a different week: 09:00 to 18:00 IST from Monday to Friday, 09:00 to 13:00 IST on Saturday, and closed on Sunday. Write add_business_minutes(start, minutes, holidays=(), week=WEEK) for it. It returns the moment that is minutes business minutes after start, so the desk can promise a deadline that lands on a minute it is open.

Arguments:

  • start: a timezone-aware datetime. Read it on the desk's clock first, start.astimezone(IST), whatever offset it carries.
  • minutes: a whole number of business minutes to add, 0 or more.
  • holidays: a collection of date values on which the desk is closed all day, whatever the week says.
  • week: a dict from a weekday number (0 for Monday to 6 for Sunday, as datetime.weekday() numbers them) to an (open, close) pair of time values. A weekday missing from the dict is a closed day. The starter defines WEEK for this desk, and the tests also pass a week of their own.

Rules the function enforces:

  1. Only open minutes count. Each day counts the minutes between its own open and close, so a Saturday counts 240 at most and a Sunday none.
  2. Starts outside the open hours move forward. A start before a day's open uses that open. A start at or after a day's close, on a closed day or on a holiday moves to the open of the next day that is open.
  3. **The result is a timezone-aware datetime in IST**, between a day's open and its close (a deadline may fall exactly at a close).
  4. **A start without tzinfo raises ValueError**, because a bare clock time names no single moment.

The starter already imports what you need and defines IST, UTC and WEEK. Write the body of add_business_minutes so every sample test passes.

Starter code · add_business_minutes.py

from datetime import date, datetime, time, timedelta, timezone

IST = timezone(timedelta(hours=5, minutes=30))  # Asia/Kolkata, +05:30
UTC = timezone.utc

# This desk's published week: weekday number (Monday is 0) -> (open, close) in IST.
# Sunday (6) is not in the dict, so the desk is closed that day.
WEEK = {
    0: (time(9, 0), time(18, 0)),
    1: (time(9, 0), time(18, 0)),
    2: (time(9, 0), time(18, 0)),
    3: (time(9, 0), time(18, 0)),
    4: (time(9, 0), time(18, 0)),
    5: (time(9, 0), time(13, 0)),
}


def add_business_minutes(start, minutes, holidays=(), week=WEEK):
    """Return the moment that is `minutes` business minutes after `start`.

    TODO: read `start` on the IST clock, then spend the minutes inside the
    open hours of each day in `week`, skipping closed days and holidays.
    Raise ValueError when `start` has no tzinfo.
    """
    return start
The sample tests · test_add_business_minutes.py
from datetime import date, datetime, time, timedelta

from add_business_minutes import IST, UTC, add_business_minutes


def test_ten_minutes_in_the_middle_of_a_monday():
    """ten business minutes added at 10:00 on a Monday end at 10:10"""
    start = datetime(2026, 10, 12, 10, 0, tzinfo=IST)
    assert add_business_minutes(start, 10) == datetime(2026, 10, 12, 10, 10, tzinfo=IST)


def test_friday_evening_carries_into_saturday_morning():
    """30 minutes fit before the Friday close; the other 30 are spent from the Saturday open"""
    start = datetime(2026, 10, 9, 17, 30, tzinfo=IST)
    assert add_business_minutes(start, 60) == datetime(2026, 10, 10, 9, 30, tzinfo=IST)


def test_saturday_closes_at_one():
    """Saturday 12:30 + 60 minutes: 30 before the 13:00 close, Sunday is closed, 30 on Monday"""
    start = datetime(2026, 10, 10, 12, 30, tzinfo=IST)
    assert add_business_minutes(start, 60) == datetime(2026, 10, 12, 9, 30, tzinfo=IST)


def test_a_full_saturday_ends_at_its_close():
    """the 240 minutes of a Saturday end exactly at 13:00"""
    start = datetime(2026, 10, 10, 9, 0, tzinfo=IST)
    assert add_business_minutes(start, 240) == datetime(2026, 10, 10, 13, 0, tzinfo=IST)


def test_a_start_after_the_saturday_close_waits_for_monday():
    """a start at 14:00 on a Saturday counts nothing until the Monday open"""
    start = datetime(2026, 10, 10, 14, 0, tzinfo=IST)
    assert add_business_minutes(start, 15) == datetime(2026, 10, 12, 9, 15, tzinfo=IST)


def test_a_holiday_friday_hands_the_minutes_to_saturday():
    """Thursday 17:30 + 60 with the Friday a holiday ends on Saturday at 09:30 on this desk"""
    start = datetime(2026, 10, 1, 17, 30, tzinfo=IST)
    end = add_business_minutes(start, 60, holidays={date(2026, 10, 2)})
    assert end == datetime(2026, 10, 3, 9, 30, tzinfo=IST)


def test_a_holiday_saturday_is_skipped():
    """Friday 17:00 + 120 with the Saturday a holiday: 60 on Friday, 60 on Monday"""
    start = datetime(2026, 10, 9, 17, 0, tzinfo=IST)
    end = add_business_minutes(start, 120, holidays={date(2026, 10, 10)})
    assert end == datetime(2026, 10, 12, 10, 0, tzinfo=IST)


def test_a_sunday_start_rolls_to_the_monday_open():
    """Sunday is not in the week, so the clock starts at 09:00 on Monday"""
    start = datetime(2026, 10, 11, 10, 0, tzinfo=IST)
    assert add_business_minutes(start, 60) == datetime(2026, 10, 12, 10, 0, tzinfo=IST)


def test_zero_minutes_on_a_sunday_land_on_the_monday_open():
    """zero minutes still move a closed-day start to the next working minute"""
    start = datetime(2026, 10, 11, 10, 0, tzinfo=IST)
    assert add_business_minutes(start, 0) == datetime(2026, 10, 12, 9, 0, tzinfo=IST)


def test_before_opening_uses_the_day_open():
    """a start at 07:15 on a Monday starts the clock at 09:00"""
    start = datetime(2026, 10, 12, 7, 15, tzinfo=IST)
    assert add_business_minutes(start, 90) == datetime(2026, 10, 12, 10, 30, tzinfo=IST)


def test_a_utc_input_is_read_in_ist():
    """10:00 UTC on a Wednesday is 15:30 on the desk's clock; the answer comes back in IST"""
    start = datetime(2026, 10, 7, 10, 0, tzinfo=UTC)
    end = add_business_minutes(start, 45)
    assert end == datetime(2026, 10, 7, 16, 15, tzinfo=IST)
    assert end.utcoffset() == timedelta(hours=5, minutes=30)


def test_the_week_argument_is_used():
    """a desk open 10:00 to 16:00 on weekdays only: Friday 15:30 + 60 ends on Monday at 10:30"""
    weekdays_only = {day: (time(10, 0), time(16, 0)) for day in range(5)}
    start = datetime(2026, 10, 9, 15, 30, tzinfo=IST)
    end = add_business_minutes(start, 60, week=weekdays_only)
    assert end == datetime(2026, 10, 12, 10, 30, tzinfo=IST)


def test_naive_datetime_is_rejected():
    """a datetime without tzinfo cannot be read on the IST clock safely"""
    try:
        add_business_minutes(datetime(2026, 10, 12, 10, 0), 10)
    except ValueError:
        return
    raise AssertionError("ValueError not raised for a naive datetime")
A hint

Saturday is where the lesson's program goes wrong for this desk: it gives every open day the same hours and treats Saturday as closed. Look the hours up for each day inside the loop, from week, instead of once before it, and let a day that week does not list behave like a holiday.

The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.

Then test yourself across the five ideas, from the ticket states to the metrics that mislead; the questions adapt to your answers as you go:

Practice that adapts to you

Practise this lesson

10 questions about 5 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 10 Does the pending state always pause the SLA resolution clock?

    Choose one answer.

    Show the answer: Question 1 of 10

    Answer: No; the clock pauses only when the agreement itself says it does.

    Read the agreement before promising a pause. A desk that assumes pending stops the clock when the agreement does not either breaches the deadline or hides the breach in the record.

  2. Question 2 of 10 A desk makes a habit of opening a fresh ticket when a fault returns, rather than reopening the old one. What does the habit do to its dashboard?

    Choose one answer.

    Show the answer: Question 2 of 10

    Answer: First-contact resolution rises and the reopen rate falls

    A duplicate inflates first-contact resolution and deflates the reopen rate at the same time, while the user had the same fault twice. Reopening is slower today and honest in every number.

  3. Question 3 of 10 A team of eight cannot submit their expenses before the Friday deadline. On the lesson matrix, this is medium impact (a team) and medium urgency (today). What is the priority?

    Choose one answer.

    Show the answer: Question 3 of 10

    Answer: P2

    Read the cell straight off the matrix. Medium impact and medium urgency sit in the middle cell, which the lesson sample reads P2.

  4. Question 4 of 10 A caller is angry about a P3 ticket. Does the anger change the priority?

    Choose one answer.

    Show the answer: Question 4 of 10

    Answer: No; priority is impact and urgency on the matrix, and anger is handled by the conversation, not by raising the number.

    The matrix is the agreement everyone shares. Changing a priority is a decision with a reason recorded, not a response to how a call feels; the de-escalation lesson handles the conversation itself.

  5. Question 5 of 10 On the lesson desk (09:00 to 18:00, Monday to Friday, no holiday that week), a ticket lands at 16:20 on a Friday with a 240-minute resolution target. How many of its business minutes are left to spend on Monday?

    Type a number.

    A hint

    Count what the Friday can still give before its close, then what Saturday and Sunday give.

    Show the answer: Question 5 of 10

    Answer: 140 minutes

    Friday 16:20 to 18:00 spends 100 minutes. Saturday and Sunday count none. The remaining 140 minutes run from Monday's 09:00 open, so the deadline is Monday 11:20+05:30.

  6. Question 6 of 10 Why does a four-hour wall-clock promise slip on a desk that works 09:00 to 18:00, Monday to Friday?

    Choose one answer.

    Show the answer: Question 6 of 10

    Answer: Wall-clock hours run through nights, weekends and holidays, and nobody is at the desk then

    A desk that promises in wall-clock hours promises outcomes it cannot deliver. The agreement names business hours, and the clock counts only the minutes the desk is working.

  7. Question 7 of 10 A customer in London writes Wednesday 23:10+01:00. What time is that on the IST clock?

    Choose one answer.

    Show the answer: Question 7 of 10

    Answer: Thursday 03:40+05:30

    Convert through UTC: 23:10+01:00 is 22:10+00:00, which is 03:40+05:30 on Thursday. The SLA clock starts from that moment on the desk's calendar, not from 23:10 on the desk's own clock.

  8. Question 8 of 10 Which of these clocks moves twice a year because of daylight saving?

    Choose one answer.

    Show the answer: Question 8 of 10

    Answer: London (GMT, BST)

    Clocks that observe daylight saving change their offset twice a year; clocks that do not keep their offset. The tz database carries the rule for each area, so a time-zone library applies the right offset for each date.

  9. Question 9 of 10 In metrics.py the desk splits T-05 the same way as T-02: two tickets, both marked as resolved at first contact, in place of one that was not. What does first-contact resolution read after both splits? (Round to the nearest 0.1.)

    Type a number.

    A hint

    Start from the report after the first split, 10 of 13, and change the two counts the second split changes.

    Show the answer: Question 9 of 10

    Answer: 85.7 % (anything from 85.65 to 85.75 counts)

    Each split adds one closed ticket and turns a miss into two first-contact closes, so 10 of 13 becomes 12 of 14, which is 85.7 %. The user received the same help as before.

  10. Question 10 of 10 A manager sees first-contact resolution, mean time to resolve and the reopen rate all improve in the same week, with backlog age flat. Which check tells a real improvement from the split-ticket trick?

    Choose one answer.

    Show the answer: Question 10 of 10

    Answer: Compare the number of tickets with the number of problems users reported

    Every rate is a share of closed tickets, so a move that adds closed tickets can lift them all at once. The ticket count against the problems reported, or a sample of tickets read by a person, is what catches it.

Interview questions

Warm-up (fresher): a VIP marks a ticket closed on their own saying ‘it works now’. The error returns ten minutes later. What state do you move it to, and why not open a fresh one?

Reopen the related ticket, so the state moves from closed back to in progress and the history travels with the work. A duplicate loses the context: the error text, the actions already tried, the notes about who was contacted. It also makes the fault look rarer than it is and counts the second contact as first-contact resolution, which flatters the dashboard without helping the user. Keep the resolution window counting from the first contact when the SLA says reopens do, so the agreement does not reset by accident, and tell the user plainly that you are reopening the earlier ticket.

Two harder cases begin where this lesson stops, one on priority and one on a customer’s time zone. Work out your answer on paper before you open the first step of each:

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Fresher to mid

    At 10:00 a sales manager's laptop will not start; she presents to a client at 10:40. A team of six finds its shared drive read-only, but local copies keep them working until tomorrow's 10:00 submission. On the lesson's 3x3 matrix, which goes first, what do you tell the team, and when do you look again?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Mid to senior

    Your desk works 09:00 to 18:00 IST, Monday to Friday, and promises P2 resolution in 4 business hours. A P2 ticket from a New York customer is raised at 2026-03-06T16:00-05:00. When is the deadline on the desk's clock, and what time do you give the customer for it? Show your working.

    Model answer, Pro. First step and follow-ups

Flashcards · 6 cards

Recall it, then check

Say the answer to yourself before you look: recalling it is what makes it stick.

  1. Which six states does a ticket move through, and what happens when the fault returns?

    New, assigned, in progress, pending, resolved and closed. A related fault that comes back reopens the ticket instead of starting a new one, so the history travels with the work.

  2. A VIP closes their own ticket and the error is back ten minutes later. Why reopen it rather than open a fresh one?

    A duplicate loses the error text, the actions tried and the contact notes. It also makes the fault look rarer and counts the second contact as first-contact resolution, which flatters the dashboard without helping the user.

  3. How is a ticket's priority set?

    From two readings, impact and urgency, looked up on the matrix the organisation has published. Changing the priority is a decision with its reason in the ticket, not a judgement about the caller.

  4. How does an SLA clock count toward a resolution target?

    In business minutes only, against the published hours and the holiday calendar. On a desk open 09:00 to 18:00 on weekdays, 60 minutes from Thursday 17:30+05:30, with the Friday a holiday, end on Monday at 09:30+05:30.

  5. A customer gives a time with no offset. What do you do before adding SLA minutes to it?

    Treat it as a question, not a start. Once the zone is known, convert the time to the desk's clock with a time-zone library, because the UK, Europe and most of the US move their clocks.

  6. Why read service desk metrics together rather than one at a time?

    Each one can be gamed alone, and a split ticket or an early close moves several at once. Read first-contact resolution, mean time to resolve, reopen rate and backlog age together, beside the ticket count.

Key takeaways

  • A ticket moves through six states (new, assigned, in progress, pending, resolved, closed), and a related fault that returns is a reopen, not a new ticket, so the history travels with the work.
  • Priority is impact and urgency read off the organisation’s published 3x3 matrix; on the sample matrix a stopped payroll server is P1 and a VIP’s forgotten password is P3, whoever called first.
  • A resolution target counts business minutes against the published hours and the holiday calendar, so 60 minutes from Thursday 17:30+05:30, with the Friday a holiday, end on Monday at 09:30+05:30.
  • Convert a customer’s time to the desk’s clock with a time-zone library before adding minutes, because the UK, Europe and most of the US move their clocks; a time with no offset is a question, not a start.
  • Each desk metric can be gamed on its own, so read first-contact resolution, mean time to resolve, reopen rate and backlog age together and beside the ticket count: a split ticket or an early close moves several of them at once.

Terms in this lesson

backlog age
The average age of the tickets that are still open at the moment the report is run. Measured in hours or days; it moves only when tickets are opened, closed or stay open longer, not when a closed ticket is split.
business-hours calendar
The published daily working hours of a service desk, such as 09:00 to 18:00 Monday to Friday. Service-level agreement clocks count minutes only inside these windows, so a wall-clock promise is replaced with a business-hours one.
first-contact resolution
The share of closed tickets that were resolved during the first contact with the user, with no later work needed. Written FCR. Easy to flatter by splitting one ticket into two or by closing early.
holiday calendar
The list of dates on which an office is closed and no business minutes elapse, such as a country's public holidays or an organisation's shutdowns. The service-level agreement reads it beside the business hours.
impact
In service-desk work: how many people a fault affects and how critical the service it stops is. One axis of the priority matrix: low, medium or high.
mean time to resolve
The average time between a ticket's creation and its resolution, taken over the closed tickets in a window. Written MTTR. Falls alongside a rising reopen rate when tickets are being closed too soon.
pending state
The state a ticket moves to while the owner is waiting on a reply, usually from the user or a vendor. The service-level agreement clock pauses while a ticket is pending only if the agreement itself names that rule.
priority matrix
A 3x3 table that reads impact against urgency and prints the priority band (such as P1 to P4) for each cell. Every organisation publishes its own matrix in its service-level agreement.
reopen rate
The share of closed tickets that had to be reopened within a window, usually a few days. A rising reopen rate beside a falling mean time to resolve is the signature of a desk closing tickets too early.
resolution target
How soon, in business hours, a service-level agreement commits the fault to be fixed for a ticket of a given priority. Measured against the business-hours calendar and the holiday calendar for the office.
response target
How soon, in business hours, a service-level agreement commits a human reply to the user after a ticket of a given priority is raised. The response clock stops at the first substantial reply.
service-level agreement
A written contract between the service desk and its users or customers, naming the targets the desk commits to for each priority (response time, resolution time) and the business hours and holidays those targets are measured against. Its short name is SLA.
urgency
In service-desk work: how fast the harm from a fault grows if it is left in place. The other axis of the priority matrix: low (no deadline), medium (today) or high (minutes to harm).

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.