Issue & PR Management
Issues and pull requests are the heartbeat of an open source project. They are where bugs get reported, features get proposed, code gets reviewed, and decisions get made. Managing them well is the difference between a project that feels alive and responsive and one that feels abandoned. The most common failure is not too few issues. It is too many unprocessed ones sitting in a growing backlog that nobody triages.
Issue Triage
Triage is the process of evaluating new issues, categorizing them, and deciding what to do with them. Without triage, the issue list becomes a graveyard of unread bug reports and unanswered questions.
Triage workflow for each new issue:
1. Read and understand the issue
Can you reproduce it? Is it clear what the reporter expects?
2. Label it
Bug, feature request, question, documentation, duplicate, etc.
Priority: critical, high, medium, low
Area: CLI, API, UI, core, docs
3. Respond
Acknowledge the report. Ask clarifying questions if needed.
"Thanks for reporting this. I can reproduce it on v3.2.1."
4. Assign or prioritize
Critical bugs: fix this week.
High priority: next release.
Medium: backlog.
Low: nice to have, might never happen.
5. Close if appropriate
Duplicates: link to the original issue.
Won't fix: explain why kindly.
Not a bug: explain the expected behavior.
Stale: no response after asking for more information.
Labels That Work
A consistent labeling system makes triage faster and helps contributors find work.
Recommended label categories:
Type labels:
bug — something is broken
feature — a new capability
enhancement — improvement to existing functionality
documentation — docs changes only
question — support request, better in Discussions
Priority labels:
critical — project is broken for most users
high — significant impact, fix soon
medium — real issue, can wait
low — minor, nice to have
Status labels:
needs-triage — not yet reviewed
needs-info — waiting for reporter to provide details
confirmed — reproduced, accepted as valid
good-first-issue — suitable for new contributors
help-wanted — maintainers want community help
wont-fix — decided not to address
Area labels (project-specific):
area/cli — command-line interface
area/api — API changes
area/core — core library
area/docs — documentation
Kubernetes uses a sophisticated label system with over 100 labels organized by SIG (Special Interest Group), priority, kind, and lifecycle stage. For smaller projects, 15-20 labels are sufficient.
Issue Templates
Issue templates reduce noise by guiding reporters toward useful information. Without them, bug reports arrive as "it doesn't work" with no version number, no steps to reproduce, and no error message.
Bug report template (/.github/ISSUE_TEMPLATE/bug_report.md):
---
name: Bug Report
about: Report a bug to help us improve
labels: bug, needs-triage
---
## Description
A clear description of the bug.
## Steps to Reproduce
1. Go to '...'
2. Click on '...'
3. See error
## Expected Behavior
What you expected to happen.
## Actual Behavior
What actually happened.
## Environment
- OS: [e.g., macOS 14.2]
- Version: [e.g., v3.2.1]
- Node.js version: [e.g., 20.10.0]
## Additional Context
Logs, screenshots, or anything else helpful.
Feature request templates follow the same pattern: problem description, proposed solution, alternatives considered. GitHub also supports YAML-based issue forms that render as structured input fields instead of free-text markdown, which are even more effective at collecting structured information.
The Stale Bot
The stale bot (typically actions/stale on GitHub Actions) automatically marks and closes issues that have had no activity for a specified period. It is controversial but practical.
Stale bot configuration example:
days-before-stale: 90 # Mark as stale after 90 days of inactivity
days-before-close: 14 # Close 14 days after being marked stale
stale-issue-label: stale
stale-issue-message: >
This issue has been automatically marked as stale because it has
not had activity in 90 days. It will be closed in 14 days if no
further activity occurs. If this is still relevant, please comment
to keep it open.
exempt-issue-labels: critical,pinned,security
Arguments for:
- Prevents the issue count from growing unboundedly
- Issues that nobody cares about for 90 days are probably not important
- Keeps the backlog manageable and the project looking maintained
- Forces prioritization: if it matters, someone will respond
Arguments against:
- Legitimate issues get closed because the reporter moved on
- Feels dismissive to reporters who took time to file issues
- Gives a false sense of productivity (closing issues is not fixing them)
- Can be seen as the project ignoring real problems
The compromise: use the stale bot for feature requests and questions, but exempt bugs and security issues. If a bug is real, it should not be closed just because nobody commented recently.
React, Next.js, and VS Code all use stale bots with varying configurations. The key is transparency: explain the policy in your CONTRIBUTING.md so reporters are not surprised.
Pull Request Reviews
PR reviews are where code quality, contributor experience, and project culture intersect. A good review improves the code and teaches the contributor. A bad review discourages the contributor and may lose them forever.
Be Kind
The first rule of code review is kindness. The person who submitted the PR volunteered their time. Even if the code needs significant changes, acknowledge the effort.
Bad review comments:
"This is wrong."
"Why would you do it this way?"
"This is not how we do things here."
"Did you even read the contributing guide?"
Good review comments:
"This approach works, but there's a subtle issue with X.
Could you try Y instead? Here's why..."
"Thanks for tackling this! I have a few suggestions to
align with our existing patterns."
"This is a great start. One thing to consider: the current
approach might cause issues when Z. What do you think about
handling that case?"
Be Clear
Vague review comments waste everyone's time. "LGTM" (Looks Good To Me) is not a review. It provides no value to the contributor and no assurance to other maintainers.
"LGTM" vs. an actual review:
"LGTM" tells you:
- Someone glanced at it
- Maybe
An actual review tells you:
- Which parts were checked (logic, tests, edge cases)
- What tradeoffs were considered
- Whether it aligns with the project's patterns
- What, if anything, should be changed
Example of a substantive approval:
"Reviewed the parsing logic and the new test cases. The approach
handles the edge cases well. One minor suggestion: consider
adding a test for empty input. Otherwise, this is good to merge."
Be Timely
PR review speed directly correlates with contributor retention. The longer a PR sits unreviewed, the more likely the contributor will lose interest and move on.
Practical review timeline:
First response: within 48 hours
Acknowledge the PR. Even "I'll review this by Friday" is enough.
Initial review: within 1 week
Provide substantive feedback. Flag blocking issues early.
Follow-up review: within 48 hours of updates
The contributor made the changes you requested. Do not make them
wait another week. Prioritize follow-up reviews over initial reviews.
Merge decision: same day as final approval
Once approved, merge promptly. Do not let approved PRs sit.
Breaking Changes
Breaking changes are the most sensitive part of maintenance. They affect every user who upgrades. Handled well, they build trust. Handled poorly, they destroy it.
Communicate Early
Breaking change communication timeline:
1. Announce the intent
Open an RFC or discussion: "We are considering changing X.
Here's why. We want your feedback."
2. Deprecation warning
In the current version, mark the old behavior as deprecated.
Print a warning: "Warning: X is deprecated and will be removed
in v4.0. Use Y instead."
3. Migration guide
Before the breaking release, publish a detailed migration guide.
Include before/after code examples for every breaking change.
4. Release with clear notes
The release notes must list every breaking change prominently.
Do not bury breaking changes in a list of 50 improvements.
5. Support window
Maintain the previous major version with security patches
for a reasonable period (6-12 months for popular projects).
Provide migration guides with before/after code examples for every breaking change. React's migration guides are exemplary, including codemods (automated code transformation scripts) that handle most breaking changes automatically.
Release Notes That Humans Can Read
Release notes are the primary way users learn what changed. Auto-generated changelogs from commit messages are a starting point, but they are not release notes. They are a changelog. Release notes tell a story.
Bad release notes (raw commit log):
- fix: resolve null pointer in parser (#456)
- feat: add --output flag (#423)
- chore: update CI config
- refactor: extract helper function
- fix: handle edge case in tokenizer (#461)
- docs: update README
Good release notes:
## v3.5.0
### New Features
- **--output flag**: You can now specify the output format directly
from the command line. Supports json, csv, and table formats.
Example: `tool export --output json data.db`
### Bug Fixes
- Fixed a crash when parsing files with null bytes (#456)
- Fixed incorrect tokenization of escaped quotes (#461)
### Thank You
Thanks to @alice and @bob for their contributions to this release.
Astro's release notes are consistently excellent. Each release includes a narrative summary, highlighted features with examples, and contributor acknowledgments. They treat release notes as a communication product, not a chore.
Common Pitfalls
-
No triage process. Issues pile up, new reports get lost among old ones, and the project looks abandoned. Even 30 minutes of triage per week makes a visible difference.
-
Issue templates that are too long. If your bug report template has 15 required fields, people will either skip it or not file the bug at all. Keep templates short: description, steps to reproduce, expected behavior, environment.
-
Stale bot closing legitimate bugs. Configure exemptions for bugs, security issues, and anything labeled as confirmed. The stale bot should clean up stale feature requests and questions, not sweep real bugs under the rug.
-
Harsh or nitpicky PR reviews for first-time contributors. A first-time contributor who receives 30 comments about code style will not submit a second PR. Fix minor style issues yourself and focus review feedback on logic and correctness.
-
Breaking changes without warning. Shipping breaking changes in a minor or patch release, or in a major release without a migration guide, erodes user trust. Follow semantic versioning and communicate breaking changes early.
-
Release notes that nobody reads. If your release notes are a raw git log, users will stop reading them. Invest 15 minutes in writing human-readable summaries for each release.
Key Takeaways
- Triage every issue: label, prioritize, respond, and close when appropriate. An untriaged backlog makes a project look abandoned.
- Issue templates guide reporters toward providing useful information. Keep them short and focused on the essentials.
- Stale bots are controversial but practical. Use them for feature requests and questions while exempting confirmed bugs and security issues.
- PR reviews should be kind, clear, and timely. "LGTM" is not a review. Aim for initial response within 48 hours.
- Breaking changes require early communication, deprecation warnings, migration guides, and clear release notes. Never surprise your users.
- Release notes are a communication product. Write them for humans, not robots.