Defect Aging and SLA Metrics: How to Measure and Report Them
Last updated: October 2026
Defect aging tells you how long each defect has been open, and an SLA tells you how long it was allowed to stay open. Most QA teams track one without the other, so an old Sev 2 sits in the backlog until a release review finds it. This guide shows how to calculate defect aging, set SLA targets by severity, and report both from Jira, Excel and SQL without misleading anyone.
What you will get
- Formulas for open age, closed age and SLA compliance
- An example SLA policy by severity you can adapt
- A decision tree for calendar days, business days or business hours
- JQL filters, Excel formulas and a T-SQL query for aging buckets
- Two fictional scenarios: an EHR upgrade and a payments API contract
- Edge cases that quietly break aging numbers
What defect aging measures
Defect aging is the time between the moment a defect is logged and either its resolution or today. The ISTQB Foundation Level syllabus treats defect reports as a core test management work product. Aging turns those reports into a time signal: which problems are waiting, and for how long.
There are two versions of the number, and mixing them is the first common error. Closed age describes how fast the team fixed things in the past. Open age describes the risk sitting in the backlog right now.
| Metric | Formula | Question it answers |
|---|---|---|
| Open defect age | as-of date − opened date | How long has this defect been waiting? |
| Closed defect age | resolved date − opened date | How long did the fix take? |
| Time in status | sum of time spent in one status | Where does the waiting happen: dev, retest or info requests? |
| SLA compliance | closed within target ÷ all closed | Did we keep our promise last period? |
| Open past SLA | count of open defects with age > target | Which promises are already broken? |
Defect age vs resolution time
Resolution time is closed age reported as an average across many defects. The TechFitFlow guide on bug tracking metrics covers mean time to resolution by severity. Aging adds what that average hides: the defects that never closed.
A team can post a fast average resolution time while a handful of hard defects sit for months. Those never enter the average until someone finally closes them. Open age by bucket is the number that exposes them.
Defect SLA or SLO: which one does your team have?
Google’s Site Reliability Engineering book draws a line that QA teams rarely draw. An SLO is a target value for a measured service level. An SLA is an agreement that attaches consequences to meeting or missing those targets.
The SRE book’s test is simple: ask what happens if the target is missed. If nothing explicit happens, it is almost certainly an SLO, whatever your process document calls it.
| Internal defect target (SLO) | Contractual defect SLA | |
|---|---|---|
| Who sets it | QA lead, dev lead and product owner | Contract between vendor and client |
| What a miss triggers | Escalation, triage discussion | Service credits, penalties, formal review |
| Clock rules | Your team decides and can change them | Written in the contract; follow them exactly |
| Typical use | Test phases, sprints, UAT | Production support, vendor-owned defects |
This guide uses “SLA” for both, because that is how most defect workflows name it. Keep the distinction in mind when you report: a missed internal target is a conversation, while a missed contractual SLA is a cost.
Setting defect SLA targets by severity
No standard body publishes universal defect SLA values. Targets depend on release cadence, team size and what a defect blocks. The table below is an example starting point for a team that works weekdays, not an industry norm.
| Severity | Example meaning | Response target | Resolution target |
|---|---|---|---|
| Sev 1 Critical | Blocks testing or a core workflow, no workaround | 1 business hour | 1 business day |
| Sev 2 High | Major function wrong, workaround is painful | 4 business hours | 3 business days |
| Sev 3 Medium | Function wrong, reasonable workaround exists | 1 business day | 10 business days |
| Sev 4 Low | Cosmetic or minor, no functional impact | 3 business days | 30 business days or next release |
Tie the targets to severity, not priority. Severity describes impact, while priority describes order of work. A low-severity defect can be high priority because a demo is tomorrow, but that should not move its SLA. The guide on priority vs severity covers that split in detail.
Rules to write down before the first report
- Start event. Usually the created timestamp. For defects logged outside office hours, decide whether the clock starts at once or at the next business hour.
- Stop event. Resolved by development, or closed after retest. Pick one per metric and label it.
- Pause conditions. Jira Service Management lets admins define start, pause and stop conditions for SLAs. Common pauses are “Waiting for information” and “Waiting for vendor”.
- Severity changes. If a Sev 2 is downgraded to Sev 3 on day 4, does the target become 10 days from the original open date? Write the rule and apply it the same way every time.
- Reopens. Continue the original clock. A reopened defect was never really fixed.
- Exclusions. Rejected, duplicate and “works as designed” defects leave the SLA population.
Where the SLA clock runs
Reopened defects resume from their previous total, not from zero. Rejected and duplicate defects leave the SLA report.
Calendar days, business days or business hours
The clock you choose can flip a defect from met to missed with no change in team behavior. A Sev 1 opened Friday afternoon and fixed Monday morning took 3 calendar days but 1 business day.
| Clock | Fits when | Watch out for |
|---|---|---|
| Calendar days | 24/7 production support; patient-facing or revenue systems | Weekday teams look slow every Monday |
| Business days | Test phases and sprints staffed Monday to Friday | Needs a holiday list that matches the team’s location |
| Business hours | Targets under 2 days, contracts written in hours | Time zones; whose working hours count |
1. Is there a contract with consequences?
Yes: use the contract’s clock, hours and time zone exactly. Stop here.
No: go to question 2.
2. Does anyone fix defects on weekends?
Yes: use calendar days.
No: go to question 3.
3. Is the shortest target under 2 days?
Yes: business hours for Sev 1 and Sev 2, business days for the rest.
No: business days for all severities.
A worked example: same defects, two clocks
The six fictional defects below are measured as of Friday, October 23, 2026, with no holidays in range. Targets come from the example policy above.
| Defect | Severity | Opened | Resolved | Calendar days | Business days | Target (business days) | Business-day result | Calendar-day result |
|---|---|---|---|---|---|---|---|---|
| PROJ-1042 | Sev 2 | Mon Oct 5 | Thu Oct 8 | 3 | 3 | 3 | Met | Met |
| PROJ-1047 | Sev 1 | Fri Oct 9 | Mon Oct 12 | 3 | 1 | 1 | Met | Missed |
| PROJ-1051 | Sev 3 | Tue Oct 6 | Open | 17 | 13 | 10 | Open, breached | Open, breached |
| PROJ-1055 | Sev 2 | Wed Oct 21 | Open | 2 | 2 | 3 | Open, within SLA | Open, within SLA |
| PROJ-1058 | Sev 4 | Thu Sep 10 | Open | 43 | 31 | 30 | Open, breached | Open, breached |
| PROJ-1060 | Sev 3 | Mon Oct 12 | Fri Oct 23 | 11 | 9 | 10 | Met | Missed |
Measured in business days, all three closed defects met their targets: 100% compliance. Measured in calendar days against the same numbers, only one did: 33%. Nothing about the work changed, only the clock.
How to calculate defect aging in Jira
Jira Software has no built-in report for defect resolution time, as of October 2026. Atlassian’s knowledge base says so and suggests a workaround: an automation rule that writes the days between created and resolved into a number field. That value is stored once, in whole days, when the issue reaches the final status.
For open defects, JQL filters give you the aging buckets directly. Relative dates must be wrapped in quotes. Atlassian’s JQL reference notes that an unquoted value is read as milliseconds, so created < -30d does not behave as intended.
-- Open bugs older than 14 calendar days, worst first
project = PROJ AND issuetype = Bug AND resolution = Unresolved
AND created < "-14d"
ORDER BY priority DESC, created ASC
-- Stale bugs: open, and nobody has touched them for 7 days
project = PROJ AND issuetype = Bug AND resolution = Unresolved
AND updated < "-7d"
-- Bugs resolved this month, for SLA compliance
project = PROJ AND issuetype = Bug AND resolved >= startOfMonth()
Correct result for the first filter: only unresolved bugs whose Created date is more than 14 days before now. If closed bugs appear, your workflow closes them without setting a Resolution.
Two checks before you trust these filters. First, open one closed bug and confirm its Resolution field is set; otherwise it still matches resolution = Unresolved. Second, in service team-managed spaces the Resolution field is not available, and Atlassian suggests statusCategory = Done instead.
JQL relative dates count calendar time from now. For business-day aging, export the filter to CSV and calculate in Excel or SQL. The step-by-step guide on creating a defect in Jira covers the fields that need to be filled for these filters to work.
How to calculate defect aging in Excel
Put the export in an Excel table named Defects with columns Opened, Resolved, Severity and Target. Add a named cell AsOf for the report date and a named range Holidays.
Calendar age:
=IF([@Resolved]="", AsOf-[@Opened], [@Resolved]-[@Opened])
Business age:
=MAX(0, NETWORKDAYS([@Opened], IF([@Resolved]="", AsOf, [@Resolved]), Holidays) - 1)
Aging bucket:
=LOOKUP([@[Business age]], {0,3,8,15,31}, {"0-2","3-7","8-14","15-30","31+"})
SLA status:
=IF([@Resolved]="",
IF([@[Business age]]>[@Target], "Open - breached", "Open - within SLA"),
IF([@[Business age]]<=[@Target], "Met", "Missed"))
SLA compliance (closed defects only):
=COUNTIFS(Defects[SLA status],"Met") /
(COUNTIFS(Defects[SLA status],"Met") + COUNTIFS(Defects[SLA status],"Missed"))
Correct result: a defect opened and resolved on the same Tuesday shows calendar age 0 and business age 0. Opened Friday and resolved Monday shows 3 and 1.
Why the - 1 and the MAX(0, …)? Microsoft’s documentation example counts both the start and end dates as workdays. Without the subtraction, a same-day fix would show an age of 1. A defect logged on a Saturday and fixed on Sunday would otherwise show -1, which the MAX removes.
Microsoft also warns that dates stored as text cause errors. CSV exports often arrive that way. Convert the Opened and Resolved columns to real dates before applying the formulas. For weekends other than Saturday and Sunday, use NETWORKDAYS.INTL.
Once ages and statuses exist, a pivot table by severity and bucket gives you the weekly view. The walkthrough on pivot tables for defect reporting shows that build step by step.
TechFitFlow toolkit (paid)
QA Defect Tracker (Excel)
Skip building this workbook. Paste your defects into the log and the aging, SLA flags and report fill in.
- SLA days per severity on a settings tab, feeding an automatic “Within SLA?” flag on every row
- Age in days from opened and closed dates against a report “as of” date (calendar days; swap in the NETWORKDAYS formula above for business days)
- Report tab: open defects by severity and status, by module, and a weekly opened-vs-closed trend
$14 · instant downloadSee what’s inside
How to calculate defect aging and SLA compliance in SQL
When defects land in a reporting database, a calendar table gives you business days without fragile date math. The query below uses SQL Server (T-SQL) and a fictional schema. Run it in a non-production environment first.
One detail matters for aging. Microsoft documents that DATEDIFF counts datepart boundaries crossed, not elapsed time. DATEDIFF(day, '2026-10-09 23:59', '2026-10-10 00:01') returns 1 after two minutes. Cast timestamps to date first so every defect is measured the same way.
-- T-SQL (SQL Server). Fictional tables:
-- dbo.Defect(DefectKey, Severity, Status, OpenedAt, ResolvedAt)
-- dbo.SeveritySla(Severity, ResolveTargetBusinessDays)
-- dbo.BusinessCalendar(CalendarDate, IsBusinessDay)
DECLARE @AsOf date = '2026-10-23';
WITH base AS (
SELECT
d.DefectKey,
d.Severity,
d.Status,
CAST(d.OpenedAt AS date) AS OpenedDate,
CAST(d.ResolvedAt AS date) AS ResolvedDate,
COALESCE(CAST(d.ResolvedAt AS date), @AsOf) AS ClockEndDate
FROM dbo.Defect AS d
WHERE d.Status NOT IN ('Rejected', 'Duplicate')
)
SELECT
b.DefectKey,
b.Severity,
b.OpenedDate,
b.ResolvedDate,
DATEDIFF(day, b.OpenedDate, b.ClockEndDate) AS AgeCalendarDays,
bd.AgeBusinessDays,
s.ResolveTargetBusinessDays AS TargetBusinessDays,
CASE
WHEN b.ResolvedDate IS NOT NULL
AND bd.AgeBusinessDays <= s.ResolveTargetBusinessDays THEN 'Met'
WHEN b.ResolvedDate IS NOT NULL THEN 'Missed'
WHEN bd.AgeBusinessDays > s.ResolveTargetBusinessDays THEN 'Open - breached'
ELSE 'Open - within SLA'
END AS SlaStatus
FROM base AS b
CROSS APPLY (
SELECT COUNT(*) AS AgeBusinessDays
FROM dbo.BusinessCalendar AS c
WHERE c.CalendarDate > b.OpenedDate
AND c.CalendarDate <= b.ClockEndDate
AND c.IsBusinessDay = 1
) AS bd
JOIN dbo.SeveritySla AS s
ON s.Severity = b.Severity
ORDER BY bd.AgeBusinessDays DESC;
Correct result: one row per defect except rejected and duplicate ones. With the six defects from the worked example, PROJ-1058 tops the list at 31 business days and “Open – breached”.
The calendar condition counts business days after the open date, up to and including the end date. That matches the Excel formula, so both tools agree on the same defect.
-- T-SQL. Weekly summary: open defects by severity and aging bucket,
-- plus SLA compliance for defects resolved in the last 30 days.
DECLARE @AsOf date = '2026-10-23';
WITH base AS (
SELECT
d.Severity,
CAST(d.OpenedAt AS date) AS OpenedDate,
CAST(d.ResolvedAt AS date) AS ResolvedDate,
COALESCE(CAST(d.ResolvedAt AS date), @AsOf) AS ClockEndDate
FROM dbo.Defect AS d
WHERE d.Status NOT IN ('Rejected', 'Duplicate')
),
aged AS (
SELECT
b.Severity,
b.ResolvedDate,
s.ResolveTargetBusinessDays AS TargetDays,
(SELECT COUNT(*)
FROM dbo.BusinessCalendar AS c
WHERE c.CalendarDate > b.OpenedDate
AND c.CalendarDate <= b.ClockEndDate
AND c.IsBusinessDay = 1) AS AgeDays
FROM base AS b
JOIN dbo.SeveritySla AS s ON s.Severity = b.Severity
)
SELECT
Severity,
SUM(CASE WHEN ResolvedDate IS NULL AND AgeDays BETWEEN 0 AND 2 THEN 1 ELSE 0 END) AS [Open 0-2],
SUM(CASE WHEN ResolvedDate IS NULL AND AgeDays BETWEEN 3 AND 7 THEN 1 ELSE 0 END) AS [Open 3-7],
SUM(CASE WHEN ResolvedDate IS NULL AND AgeDays BETWEEN 8 AND 14 THEN 1 ELSE 0 END) AS [Open 8-14],
SUM(CASE WHEN ResolvedDate IS NULL AND AgeDays BETWEEN 15 AND 30 THEN 1 ELSE 0 END) AS [Open 15-30],
SUM(CASE WHEN ResolvedDate IS NULL AND AgeDays > 30 THEN 1 ELSE 0 END) AS [Open 31+],
SUM(CASE WHEN ResolvedDate IS NULL AND AgeDays > TargetDays THEN 1 ELSE 0 END) AS [Open past SLA],
CAST(
SUM(CASE WHEN ResolvedDate >= DATEADD(day, -30, @AsOf) AND AgeDays <= TargetDays THEN 1.0 ELSE 0 END)
/ NULLIF(SUM(CASE WHEN ResolvedDate >= DATEADD(day, -30, @AsOf) THEN 1 ELSE 0 END), 0)
AS decimal(5, 2)) AS [SLA compliance 30d]
FROM aged
GROUP BY Severity
ORDER BY Severity;
Correct result: one row per severity. The bucket columns add up to that severity’s open count. SLA compliance is NULL, not zero, for a severity with no resolved defects in the window.
Oracle: subtracting two DATE values returns days as a number, so use TRUNC(resolved_at) - TRUNC(opened_at) for calendar age. Snowflake: it also has a DATEDIFF function; check its boundary behavior in the Snowflake documentation before you port the query.
Reporting defect aging: five numbers that hold up
A weekly aging report needs fewer numbers than most teams send. These five answer the questions a release manager actually asks.
- Open defects by severity and aging bucket. The shape of the backlog. A growing 31+ column is a warning even when totals look flat.
- Open past SLA, by owner team. Names a place to act, not a percentage to debate.
- SLA compliance for defects closed this period. The promise-keeping rate. Report the denominator next to it.
- Median open age by severity. Less distorted by one ancient defect than the average.
- Stale count. Open defects with no update in 7 days. Often the cheapest to fix, because nobody is working them.
| Statistic | Open business ages 13, 2, 31 | What it tells you |
|---|---|---|
| Mean | 15.3 days | Pulled up by the single oldest defect |
| Median | 13 days | The typical open defect |
| Maximum | 31 days | The defect to name in the meeting |
Scenario 1: an EHR upgrade with a vendor in the loop
Lakeside Regional Health, a fictional hospital system, runs regression testing for a quarterly EHR upgrade. The test window is three weeks, followed by a change freeze before go-live. Compliance wants signed evidence of every Sev 1 and Sev 2 resolution.
On day 6, a tester logs PROJ-1042, a Sev 2. Medication reconciliation drops a home medication for test patient “Test, Alpha”, MRN 000123. Triage traces it to vendor-delivered content, so the internal team cannot fix it alone.
The SLA report shows PROJ-1042 breached on day 9 and the dev lead objects. The team waited four days on the vendor. Both views are true, so the team reports two clocks:
- Total age: the release risk. Leadership needs it for the go/no-go call.
- Internal age: total age minus time in “Waiting for vendor”. This is the number the internal SLA applies to.
The constraint that shapes the fix is the freeze date, not the SLA. A Sev 2 still open at freeze needs a documented workaround or a delay decision. Showing vendor wait time separately moves that conversation to the vendor manager a week earlier.
Scenario 2: a payments API with a contractual SLA
Northgate Payments, a fictional processor, supports a bank partner under a contract. Production Sev 1 defects must be resolved within 8 business hours, measured in the bank’s time zone, or service credits apply. By the SRE definition, that is a true SLA.
The development team sits in another time zone and works a different day. Their internal tracker measured in local business days, so a defect could look healthy internally while the contractual clock had already expired.
The fix was to report the contractual clock exactly as written, in the bank’s hours, and to set a tighter internal target as an SLO. The internal target gives a buffer before money is at stake. Every Sev 1 ticket stores both the contract deadline timestamp and the internal one.
Edge cases that break aging numbers
- Migrated tickets. After a tool migration, Created can be the import date. Every legacy defect then looks young. Keep the original open date in its own field.
- Bulk closures. A release clean-up that closes 80 old defects in one afternoon wrecks the resolution-time average for that week. Report “closed as won’t fix” separately.
- Severity downgrades. A Sev 2 that misses its SLA and is quietly downgraded to Sev 3 disappears from the breach list. Log severity changes and report the original severity too.
- Reopens. Starting a new clock on reopen hides fixes that did not work. Continue the original clock and count reopens on their own.
- Weekend logging. Automated test runs log defects at 2 a.m. Saturday. Decide whether the clock starts then or at the next business hour.
- Holidays by location. A team split across countries has different holiday lists. Use the list for the team that owns the fix, or the one named in the contract.
Common mistakes with defect aging and SLA reports
| Mistake | Why it hurts | Fix |
|---|---|---|
| Reporting only average resolution time | Defects that never close are invisible | Add open age by bucket |
| Counting rejected and duplicate defects | Inflates compliance with fast, empty closures | Exclude them from the SLA population |
| Calendar days for a weekday team | Every Friday defect looks late | Business days with a holiday list |
| SLA tied to priority | Targets move whenever the plan changes | Tie targets to severity |
| No written pause rules | Every breach becomes an argument | Agree start, pause and stop events first |
| Compliance % without the denominator | 100% of 2 looks like 100% of 200 | Show “x of y” next to every rate |
FAQ
What is defect age in software testing?
Defect age is the time a defect has been open. For an open defect it runs from the logged date to today. For a closed defect it runs from the logged date to resolution.
How do you calculate defect aging?
Subtract the opened date from the resolved date, or from the report date if the defect is still open. Decide first whether you count calendar days, business days or business hours. In Excel, use NETWORKDAYS minus 1 for business days.
What is the difference between an SLA and an SLO for defects?
An SLO is a target. An SLA is an agreement with consequences, such as service credits, attached to missing the target. Most internal QA targets are SLOs, even when the team calls them SLAs.
Should defect aging count weekends and holidays?
Count them only if someone works defects on those days. A weekday test team should use business days and a holiday list, or its weekend defects will look late. Production support for 24/7 systems usually counts calendar time.
How do you track defect aging in Jira?
Use JQL filters such as created < "-14d" with resolution = Unresolved for open aging buckets. Jira Software has no built-in resolution time report, so Atlassian suggests an automation rule that stores days to resolve in a number field.
Next steps
Write down your clock rules before you report a single aging number. Start, stop, pause, reopen and severity-change rules decide whether your SLA report is trusted or argued over.
- Agree the start, pause and stop events with the dev lead and product owner, and record them in your test plan.
- Pick a clock with the decision tree above, and build a holiday list for the team that owns fixes.
- Set up the three JQL filters and export them weekly into Excel or your reporting database.
- Send the five-number report for four weeks, then review whether the targets match reality. If you would rather start from a finished workbook, the QA Defect Tracker (paid) has the log, SLA flags and report tab built in.
Sources
- Google, Site Reliability Engineering, Chapter 4: Service Level Objectives
- Atlassian, Jira Cloud documentation: JQL fields
- Atlassian Knowledge Base: Resolution Time Report for Jira Projects
- Atlassian, Jira Service Management Cloud: Set up SLA conditions
- Microsoft Support: NETWORKDAYS function
- Microsoft Learn: DATEDIFF (Transact-SQL)
- ISTQB: Certified Tester Foundation Level (CTFL) v4.0
- ISO: ISO/IEC/IEEE 29119-3:2021, Software testing, Part 3: Test documentation
Download the Defect Aging & SLA Checklist (PDF)
Two printable pages: a clock-rules worksheet, a blank SLA policy table by severity, the five weekly report numbers, and the Excel, JQL and SQL formulas from this guide.
More free templates, cheat sheets and toolkits: TechFitFlow Resources
