Triaging Incoming Issues Efficiently When Your OSS Project Blows Up
Your project hit the front page of Hacker News last night. By morning you have 200 new issues, half of which are duplicates, a third of which are feature requests disguised as bugs, and a handful that are actually critical. Congratulations β and good luck.
The instinct is to start replying immediately. Resist it. Without a triage system, you'll spend your energy on the loudest issues rather than the most important ones, and legitimate bug reporters will feel ignored while you answer the same question for the fifteenth time.
What you'll learn
- How to set up a label system that makes triage fast and consistent
- A repeatable workflow for processing a flood of new issues
- How to handle duplicates, vague reports, and feature requests without burning out
- What to automate so you're not doing the same manual work every time
- How to communicate with reporters in a way that builds community rather than killing it
Prerequisites
This guide assumes you're hosting on GitHub, but the principles apply to GitLab or any issue tracker. You'll need maintainer access to configure labels, issue templates, and branch protection. Familiarity with GitHub Actions helps for the automation sections.
Build a Label Taxonomy Before Anything Else
Labels are the backbone of any triage system. Without them, your issue list is a flat pile of text. With them, it becomes a filterable, assignable queue.
Keep your label set small and meaningful. A label nobody uses wastes screen space. Here's a starting taxonomy that works at scale:
| Label | Purpose |
|---|---|
type: bug | Confirmed broken behavior |
type: feature | New functionality request |
type: question | Should be routed to Discussions |
type: docs | Documentation gap or error |
status: needs-repro | Reporter hasn't provided enough info |
status: confirmed | You've reproduced or verified it |
status: duplicate | Covered by another issue |
status: wontfix | Out of scope or intentional |
priority: critical | Data loss, security, or major regression |
good first issue | Suitable for new contributors |
Create these labels with consistent colors: red shades for priority, blue for type, yellow for status. The color coding helps you scan a list in seconds without reading every label name.
Install Issue Templates Immediately
If you haven't already, set up issue templates before you process a single new issue. Every report filed without a template is a report that will probably require a follow-up question, and follow-up questions slow everything down.
Create a .github/ISSUE_TEMPLATE/ directory with at least two templates: one for bugs and one for feature requests. Here's a minimal but effective bug report template:
---
name: Bug Report
about: Something is broken
labels: type: bug, status: needs-repro
---
## What happened?
## What did you expect to happen?
## Steps to reproduce
1.
2.
3.
## Environment
- OS:
- Version:
- Node/Python/etc version:
## Minimal reproduction (link or snippet)
The labels field in the front matter auto-applies labels when someone opens an issue using this template. That alone cuts manual labeling work significantly.
Also add a config.yml in that same directory to redirect questions to GitHub Discussions:
blank_issues_enabled: false
contact_links:
- name: Ask a Question
url: https://github.com/yourorg/yourrepo/discussions
about: Use Discussions for questions and help requests
This prevents a large class of issues from being filed in the wrong place without you having to say it manually every time.
The Triage Workflow: Process, Don't Solve
Triage and resolution are different activities. Mixing them is how you end up spending four hours on one issue while 50 others go untouched. Set a rule for yourself: during triage, your only job is to classify and route.
Work through new issues in order and ask four questions for each one:
- Is it a duplicate? Search for existing issues before doing anything else. If it is, close it with a link to the canonical issue and apply
status: duplicate. One sentence is enough. - Is it in scope? Feature requests that don't fit the project's direction should be closed as
status: wontfiximmediately, with a brief explanation. Leaving them open invites debate. - Does it have enough information? If not, apply
status: needs-repro, post a reply asking for the missing details, and move on. Don't try to reproduce it yet. - Can you confirm it? Only if yes to all the above should you try to reproduce. If you can, apply
status: confirmedand a priority label.
This process should take 2β5 minutes per issue during triage. If you're spending longer, you've slipped into resolution mode.
Automate the Repetitive Parts
You will close a lot of duplicate issues. You will ask for reproduction steps a lot. Automation doesn't replace your judgment, but it handles the mechanical repetition so you don't have to type the same response forty times.
Stale issue bot
GitHub's official actions/stale action marks issues inactive after a configurable number of days and closes them if there's still no activity. This is particularly useful for status: needs-repro issues where the reporter never followed up.
name: Close stale issues
on:
schedule:
- cron: '0 9 * * 1'
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
with:
stale-issue-message: 'This issue has been inactive for 30 days. It will be closed in 7 days unless there is new activity.'
close-issue-message: 'Closing due to inactivity. Reopen if this is still relevant.'
days-before-stale: 30
days-before-close: 7
stale-issue-label: 'status: stale'
exempt-issue-labels: 'status: confirmed,priority: critical'
The exempt-issue-labels key ensures confirmed bugs and critical issues are never auto-closed, even if discussion goes quiet.
Saved replies
GitHub supports saved replies in your account settings. Create a library of responses for your most common situations: duplicate closes, needs-repro requests, wontfix explanations, and directing people to Discussions. Having these ready means triage stays fast even on days when your attention is low.
Handling the Three Hard Categories
Security reports
If someone files a potential security vulnerability as a public issue, close it immediately and ask them to use your private security disclosure channel. Add a SECURITY.md file to the repo root that explains your disclosure process. GitHub surfaces this file automatically when someone tries to open an issue.
Angry or rude reporters
You don't have to engage with hostility on your own time. A single calm response pointing to your code of conduct is appropriate. If behavior continues, close the issue and apply GitHub's block or hide-comment features. Your project's culture is set by what you tolerate in the first 48 hours of a surge.
Vague performance complaints
Reports like
π€ Share this article
Sign in to saveRelated Articles
Comments (0)
No comments yet. Be the first!