Pull Request Cycle Time Calculator
Measure pull request cycle time from CSV timestamps, compare median and slow-tail percentiles, and flag pickup delays or dirty rows.| PR | Started UTC | Merged UTC | Cycle | Pickup | Signal | Copy |
|---|---|---|---|---|---|---|
| {{ row.id }} | {{ row.start_at }} | {{ row.merged_at || 'Open' }} | {{ durationLabel(row.cycle_hours) }} | {{ durationLabel(row.pickup_hours) }} | {{ row.signal }} |
| Priority | Signal | Evidence | Next action | Copy |
|---|---|---|---|---|
| {{ row.priority }} | {{ row.signal }} | {{ row.evidence }} | {{ row.next_action }} |
Introduction:
A cycle-time trend is only comparable when every pull request starts and stops under the same policy. Counting from creation captures draft and author preparation time. Counting from ready for review narrows attention to the review queue, but it can hide long draft periods. The finish is merge, so this measure does not include deployment time after the pull request closes.
Elapsed time exposes several kinds of delay that a single average can blur. The first-review wait points to reviewer pickup. Time after that may reflect discussion, revisions, approval, continuous-integration work, or merge ownership. A long total does not identify the cause on its own, which is why row-level timestamps remain important.
- Cycle time
- Elapsed calendar time from the selected start timestamp to merge.
- Review pickup
- Elapsed time from the selected start to the first review timestamp, or approval when no earlier review timestamp exists.
- Slow-tail percentile
- A value such as P85 or P95 that shows how long most completed pull requests finished within, while keeping unusually slow rows visible.
Percentiles complement the mean and median. A median describes the middle completed pull request, while P85 and P95 emphasize the slower end of the distribution. Small samples make these percentiles sensitive to individual rows, so repository scope, date window, start policy, timestamp quality, and inclusion rules should remain stable between comparisons.
Open pull requests need a different measure because their cycle has not ended. Including their current age as if it were a completed duration would mix censored and finished work. Invalid timestamps also need correction rather than silent inclusion. The most useful review starts with clean rows, then examines the longest cycles instead of treating the summary as a performance score for individuals.
Cycle time can reveal queueing and handoff friction, but it cannot explain code quality, change value, incident risk, or reviewer difficulty. Large and urgent changes may legitimately take longer. Use the measure to find work worth discussing, not to reward speed without context.
How to Use This Tool:
Use one timestamp policy and one repository or team boundary for each comparison window.
- Paste or load Pull request CSV. A header may use common aliases for pull-request ID, creation, readiness, first review, approval, merge, status, and changed lines.
- Enter the Repository or team label and choose Created or Ready for review as the cycle start. If Ready is selected but a row lacks that timestamp, creation is used and a parser note is recorded.
- Set the Cycle target and Review pickup target in elapsed hours. Set Large-change flag to zero to disable it, or enter the minimum changed-line count that should be flagged.
- Review parser notes and invalid-row counts before comparing statistics. Correct timestamps that cannot be parsed, fall before the selected start, or place a review outside its cycle window.
- Use the ledger to inspect the slowest completed rows, then compare average, median, P85, P95, pickup delay, and target misses with the same policy in the next reporting window.
Interpreting Results:
Read the median as the middle completed cycle and P85 or P95 as the slower tail. When the mean is much higher than the median, a few long-running pull requests may be pulling the average upward. Open rows appear in the ledger but are excluded from completed-cycle statistics.
A cycle is a target miss only when its elapsed time is greater than the target. Equality is inside the target. Review pickup uses the same strict greater-than rule. A large change is flagged when changed lines are greater than or equal to the configured threshold.
Trace a slow row through pickup, review, approval, and merge timing before deciding what to change. A high pickup delay suggests routing or ownership work; a long approval-to-merge tail points elsewhere. Compare teams only when timestamp policies and work types are genuinely similar.
Technical Details:
Timestamps are interpreted as UTC. A date without a time becomes midnight UTC, and a timestamp without a zone is also treated as UTC. The selected cycle start is creation or a recorded ready-for-review time; when Ready is selected and missing, creation is the documented fallback.
Formula Core
For merged pull request i, elapsed cycle hours are the merge timestamp minus the selected start timestamp, divided by milliseconds per hour:
Target miss rate uses only merged rows and counts durations strictly greater than target T:
Percentiles use linear interpolation at position r = (n − 1)q in the sorted durations. If r lies between indexes j and j + 1, the fractional distance blends those two observations:
Rule Core
| Condition | Result |
|---|---|
| No merge timestamp | Row remains open and is excluded from completed-cycle statistics. |
| Merge before selected start | Row is invalid and excluded. |
| First review missing but approval present | Approval becomes the reviewer signal. |
| Review signal outside start-to-merge window | Pickup is unavailable and a parser note is recorded. |
| Cycle > target | Over target takes precedence over pickup and size flags. |
| Pickup > pickup target | Pickup slow applies when the cycle is not already over target. |
| Changed lines ≥ enabled threshold | Large change applies after the two time checks. |
Privacy and Accuracy Notes:
The CSV is parsed in the browser and is not uploaded to a calculation service. Remove sensitive titles or identifiers before sharing screenshots or exported results.
Results use elapsed calendar hours, not business hours, working days, or local holidays. The parser accepts up to 1,000 valid rows and 1,048,576 source characters. Missing or inconsistent timestamps and values without explicit zones can materially change the summary, so preserve one export policy across reporting windows.
Worked Examples:
Two completed pull requests
Suppose created-to-merge cycles are 8 and 12 hours against a 10-hour target, with first-review waits of 2 and 6 hours. Average and median cycle time are both 10 hours, but P85 is 11.4 hours and P95 is 11.8 hours. One of the two rows is strictly over target, so the miss rate is 50%. Median pickup is 4 hours. The percentiles reveal the slow row even though the median sits exactly on the target.
References:
- DORA's software delivery performance metrics, DORA.
- About pull request reviews, GitHub Docs.