Stalled Pull Requests Detection: A Step-by-Step Guide for Engineering Leaders
Stalled pull requests silently erode engineering velocity by breaking developer flow, creating merge conflicts, and masking deeper team dysfunction. This guide gives engineering managers, CTOs, and technical leads a repeatable stalled pull requests detection process to surface blocked PRs early — before they become sprint-killing delivery blockers.
Stalled pull requests are one of the quietest killers of engineering velocity. A PR that sits unreviewed for three days doesn't just delay a feature — it breaks a developer's flow, creates merge conflicts, and signals something deeper about how your team is operating.
Maybe reviewers are overloaded. Maybe the PR is too large to reasonably review. Maybe the work touches a sensitive area of the codebase and nobody wants to be the one to approve it. Whatever the cause, stalled PRs compound fast. One blocked PR becomes two, then five, and suddenly your sprint is underwater and nobody quite knows why.
The frustrating part is that most teams only discover the problem after the damage is done — during a retrospective or when a frustrated developer flags it in standup. By then, you've already lost the time.
This guide is for engineering managers, CTOs, and technical leads at startups who want to get ahead of that cycle. You'll learn how to set up a reliable, repeatable process for stalled pull requests detection — one that surfaces problems early, before they become delivery blockers.
We'll walk through defining what "stalled" actually means for your team, identifying the right data sources, setting detection thresholds, configuring alerts, and using that signal to take action without micromanaging your developers. By the end, you'll have a working system that catches PR stalls as they happen, not after the fact.
Step 1: Define What "Stalled" Actually Means for Your Team
Before you can detect a stalled pull request, you need a shared definition of what stalled means. This sounds obvious, but most teams skip it and end up with detection systems that either cry wolf constantly or miss real problems entirely.
A generic threshold won't cut it. A four-hour window might be exactly right for a fast-moving startup shipping daily. A 24-to-48-hour window might be more appropriate for teams with reviewers distributed across time zones, where a PR opened at end-of-day in London genuinely can't be reviewed until morning in San Francisco. Your definition has to reflect your actual working rhythm, not an industry average.
More importantly, "stalled" isn't a single state. There are meaningfully different stall types, each with a different root cause and a different required response:
Awaiting first review: The PR has been open and no reviewer has engaged. This is often a routing or visibility problem.
Awaiting re-review after changes: The author has addressed feedback but the reviewer hasn't returned. This is a follow-through problem.
Blocked on author response: A reviewer left comments and the author hasn't responded or pushed updates. This might be a prioritization or clarity problem.
Stuck in CI/CD: The PR is technically ready for review but a failing pipeline is blocking progress. This is a tooling or infrastructure problem.
Each of these needs a different intervention. Lumping them together under one "stalled" label makes your detection signal noisy and your responses reactive rather than targeted.
Once you've mapped your stall types, document your thresholds in writing. Put them in your team handbook, your Linear project description, or wherever your working agreements actually live. Thresholds that exist only in someone's head aren't thresholds — they're opinions that will shift every time there's pressure to ship.
One common mistake worth avoiding: setting a single universal threshold across all PR types. A PR touching core authentication infrastructure deserves a different urgency level than a documentation update. Consider categorizing by target branch, PR label, or the module being changed. A "critical path" tag on certain PRs can justify a tighter threshold without applying that same pressure to low-stakes changes.
The success indicator for this step is simple: any engineer on your team should be able to look at a PR and answer "is this stalled?" with a yes or no, based on a written definition, without asking a manager. If that's not possible yet, your definition needs more work before you move on.
Step 2: Identify Your Data Sources and Connect Them
With your definitions in place, the next step is figuring out where the data actually lives and how you're going to get it into a form you can query.
Start by mapping your tools. For most startup engineering teams, the core sources are your version control platform (GitHub or similar) for pull request state and timestamps, your project management tool (Linear or similar) for linked issues and priority context, and your CI/CD pipeline for build and check status. These three together give you a much richer picture than any single source alone.
Confirm you have API access or webhook capability for each. Most modern platforms expose PR lifecycle events — opened, review requested, reviewed, approved, merged, closed — via webhooks or REST APIs. You'll want to capture timestamps for each of these events, not just the current state, because stall detection is fundamentally about elapsed time between events.
Be honest about your blind spots. If your team routinely discusses PRs in Slack threads, that context won't appear in your structured data. A reviewer might have verbally agreed to look at something in a standup, but your data will show the PR as unreviewed. Acknowledging these gaps upfront prevents you from over-interpreting the signals you do capture. Your detection system will be useful even with incomplete data — just don't treat it as a complete picture of everything happening.
The connection between PR data and issue data is particularly valuable and often overlooked. PR age alone tells you a PR is old. It doesn't tell you why. Linking to issue context from Linear reveals whether the stall is a technical blocker, a dependency on another team, or simply a prioritization problem where the work was deprioritized and nobody updated the PR status. Those three situations require completely different responses.
For teams using an engineering intelligence platform like Progress, this step is largely handled by native integrations with GitHub and Linear. Data ingestion is continuous and doesn't require you to build or maintain a custom pipeline. The connections between PR state, issue context, and team activity are made automatically, which means you can move directly to analysis rather than spending engineering time on data plumbing.
The success indicator here is practical: you should be able to pull a list of all open PRs with their timestamps, reviewer assignments, and linked issue status from a single query or dashboard view. If you need to manually cross-reference three different tools to assemble that picture, your data integration isn't complete yet.
Step 3: Set Detection Thresholds and Stall Signals
Now you translate your Step 1 definitions into measurable signals your system can actually evaluate. This is where the conceptual work becomes operational.
For each stall type you identified, define the specific metric and threshold. For example: "Time since last review request greater than 24 hours with no reviewer activity equals an awaiting-first-review stall." Write it out that explicitly. Vague thresholds produce inconsistent detection.
The more powerful approach is to layer multiple signals for accuracy. A single signal is a weak indicator. A PR open for 48 hours is mildly concerning. A PR open for 48 hours, with no reviewer assigned, linked to an issue marked as high priority, on a branch targeting main — that's a strong stall signal worth acting on immediately. Compound signals dramatically reduce false positives and help you prioritize which stalls actually matter.
Build time-zone awareness into your thresholds from the start. If your team is distributed, a PR opened at 5pm on a Friday in one time zone shouldn't trigger a stall alert before business hours resume for the relevant reviewers. Raw clock time is a poor proxy for actual working time. Adjust your thresholds to reflect when people are actually available to review, not just how many hours have elapsed since the PR was opened.
Consider PR size as a modifier on your thresholds. Large PRs — high line count, many files changed across multiple modules — often stall because they're genuinely difficult to review in a single sitting. If you flag a 1,200-line PR with the same urgency as a 40-line bug fix, you're conflating two very different situations. Flagging large PRs separately lets you address the actual root cause (the PR is too big to review efficiently) rather than just the symptom (the review is taking too long).
Platforms like Progress compute these operational signals automatically, flagging stalled work and emerging risks without requiring you to write and maintain custom query logic. The detection runs continuously against your ingested data, which means you're not relying on someone remembering to run a report.
The success indicator for this step is a written signal definition for each stall category, with a threshold value, a time-zone adjustment where relevant, and a severity level — warning versus critical. Warning means "someone should look at this soon." Critical means "this needs attention today." If you can't distinguish between those two levels in your signal definitions, your alerts will be uniformly urgent, which is the same as uniformly ignorable.
Step 4: Configure Alerts and Routing
Detection without notification is just a report nobody reads. This step is about making sure the right signal reaches the right person at the right time — and that when it does, they know exactly what to do with it.
Start by deciding who gets notified and at what threshold. The PR author, the assigned reviewer, and the engineering manager typically need different information at different points. A reasonable starting structure: the author gets a nudge at the 24-hour mark, the assigned reviewer gets a direct prompt at the same threshold, and the manager gets visibility at 48 hours if the stall persists. Escalating gradually prevents alert fatigue while ensuring nothing falls through the cracks.
Choose your notification channel deliberately. Slack DMs create noise and get ignored, especially for engineers who receive dozens of messages a day. A dedicated channel — something like #eng-alerts — with structured, consistently formatted messages is much easier to triage. Some teams prefer daily digest summaries over real-time pings, particularly for warning-level stalls. Real-time alerts work better for critical-level stalls where delay has immediate delivery impact.
Write alert messages that include context, not just a PR link. A useful alert reads something like: "PR #412 (Auth refactor) has been awaiting review for 31 hours. Reviewer: @sarah. Linked issue: [critical] Login flow bug. Last activity: author pushed changes 2 days ago." An unhelpful alert reads: "PR stalled." The difference is whether the recipient can take action immediately or needs to click through multiple tools to understand what's happening.
Set escalation logic so alerts don't just die in a channel nobody checks. If a stall persists past a second threshold — say, 72 hours — route it to a manager or add it automatically to the next standup agenda. The escalation path should be documented and understood by the team so there's no ambiguity about what happens when something is ignored.
Alert fatigue is a real risk here. If every minor delay triggers a notification, the team will start filtering out all alerts, including the important ones. Start with conservative thresholds — err on the side of fewer, higher-confidence alerts — and tighten them as your team builds the habit of responding. It's much easier to add sensitivity over time than to rebuild trust in a signal the team has learned to ignore.
The success indicator: when a PR stalls, the right person receives a clear, actionable alert within the defined window, and your team has a documented response protocol for what to do next. If people are receiving alerts but not acting on them, the problem is usually message quality or routing — not the detection itself.
Step 5: Review the Signal in Your Regular Cadence
Detection systems don't run themselves — or rather, they can surface signals automatically, but someone still has to close the loop. This step is about embedding PR health review into your existing team rhythm so it happens consistently, not just when someone remembers to check.
The simplest approach is to attach a brief PR stall review to a meeting that already exists. The start of daily standup works well for teams that have a strong standup culture. A weekly engineering sync or Monday morning lead check-in works better for teams where standup is more ad-hoc. The key is that it happens on a predictable schedule, not on demand.
Use a simple triage format to keep the review fast. For each stalled PR, answer three questions: what's blocking it, who needs to act, and what's the deadline impact? Two minutes per PR maximum. The goal is to identify and assign ownership, not to solve the problem in the meeting. If a PR needs deeper discussion, take it offline immediately after the review.
One important distinction to make during triage: is this a process stall or a technical stall? A process stall — reviewer overloaded, PR too large, unclear ownership — needs a process response like reassignment or breaking the PR into smaller pieces. A technical stall — failing CI, unresolved dependency, merge conflict — needs a technical response. Conflating the two leads to the wrong person being assigned the wrong action.
Engineering intelligence platforms like Progress surface initiative and work-stream health alongside stalled PR signals, which gives leaders a broader view. You can see whether a stall is isolated or part of a pattern affecting multiple workstreams simultaneously. That context changes the urgency and the response — a single stalled PR is a minor friction point; five stalled PRs clustered around the same module is a signal that something structural needs attention.
The success indicator for this step: every stalled PR flagged by your detection system has a named owner and a documented next action within 24 hours of being surfaced. If PRs are being flagged but ownership isn't being assigned, the review cadence isn't working yet.
Step 6: Analyze Patterns and Fix Root Causes
Detection is reactive. It tells you what's stalled right now. Pattern analysis is where you get ahead of the problem entirely — where you stop treating symptoms and start fixing the conditions that produce stalls in the first place.
Once you've been running your detection system for two to four weeks, you'll have enough data to look for recurring patterns. The questions to ask: Are the same reviewers appearing on stalled PRs repeatedly? Are stalls clustering in specific parts of the codebase? Are they more common on certain days of the week, or after certain types of changes?
Each pattern tends to point to a specific root cause:
PRs stalling on the same reviewer repeatedly usually signals reviewer overload or unclear ownership. That person has become a de facto bottleneck, and the fix is distributing review responsibility more deliberately — through explicit rotation, ownership documentation, or expanding who has the context to review certain areas.
PRs stalling in a specific module or directory often signals high complexity or insufficient documentation in that area. Reviewers may be hesitant to approve changes they don't fully understand. The fix might be better inline documentation, architectural decision records, or a dedicated knowledge-sharing session for that part of the codebase.
PRs stalling on Fridays or before holidays often reflects a cultural norm — nobody wants to approve something they can't monitor over the weekend. This is worth naming explicitly as a team and deciding whether it's a policy you want to formalize or a habit you want to change.
Use the pattern data to make structural changes and then track whether those changes actually work. If you introduce a PR size limit and stall rates in that module drop over the following two weeks, you've confirmed the root cause. If they don't change, keep investigating. The data should be driving your interventions, not just validating decisions you've already made.
Progress's team momentum analysis connects PR-level signals to broader delivery trends, so you can see whether a structural change — like a reviewer rotation or a size limit — is actually improving team-level delivery pace, not just reducing the number of stall alerts. That connection between the tactical fix and the strategic outcome is where engineering intelligence platforms add their most distinctive value.
The success indicator: you can point to at least one structural change made in direct response to stall pattern data, with a before-and-after comparison showing its effect. If your detection system has been running for a month and you haven't made any structural changes based on what you've learned, you're using it as a monitoring tool rather than an improvement tool.
Putting It All Together: Your Stall Detection Checklist
You now have a complete, six-step system for stalled pull requests detection. Here's a quick-reference checklist to verify your setup is operational before you rely on it:
Step 1 — Define stall types: You have a written definition for each stall category (awaiting first review, awaiting re-review, blocked on author, stuck in CI), with thresholds documented in your team handbook or project tool.
Step 2 — Connect data sources: GitHub and Linear (or equivalents) are connected and you can pull open PRs with timestamps, reviewer assignments, and linked issue status in a single view.
Step 3 — Set detection signals: Each stall type has a measurable threshold, a time-zone adjustment where relevant, and a severity level (warning vs. critical).
Step 4 — Configure alerts: Notifications are routed to the right people at the right thresholds, messages include context not just PR links, and escalation logic is documented.
Step 5 — Embed in cadence: PR stall review is part of an existing recurring meeting, with a triage format that assigns ownership within 24 hours.
Step 6 — Analyze patterns: After two to four weeks, you're reviewing recurring patterns and making at least one structural change based on what the data shows.
One final note on the cultural dimension: stall detection works best when it's framed as helping developers get unblocked faster, not as monitoring individual performance. The goal is signal, not surveillance. When your team understands that the system exists to remove friction from their work — not to track their output — adoption is much smoother and the data you get back is more honest.
For teams that want automated detection without building and maintaining custom alert infrastructure, Progress handles the ingestion, signal computation, and pattern analysis automatically — so your engineering leaders spend time acting on insights rather than building the plumbing to surface them. Learn more about our services and see how engineering intelligence can turn your PR data into decisions.