5 min read
On this page

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.