Skip to main content

Module 14: Contributing to PostgreSQL

PostgreSQL is one of the most welcoming open-source projects — and arguably the most technically rigorous. Unlike many open-source communities where a pull request can be merged by a single maintainer after a cursory review, PostgreSQL operates on a mailing-list-driven, consensus-based model that has produced one of the most stable and well-engineered codebases in the history of software. This module guides you through the contribution process, from finding issues to getting your first patch committed. It is not a quick weekend project — but neither is building a reputation as someone who can be trusted with infrastructure that runs the world’s financial systems, healthcare records, and government databases.
Estimated Time: 8-10 hours
Difficulty: Expert
Prerequisite: Module 13 (Source Code)
Outcome: First accepted contribution

14.1 PostgreSQL Community Structure

Think of the PostgreSQL community like a traditional guild system. You don’t walk in and start forging swords on day one. You apprentice, you prove yourself on small tasks, you earn trust over years. This is intentional — PostgreSQL stores data people cannot afford to lose, and the community treats that responsibility with the gravity it deserves.
Why mailing lists instead of GitHub? PostgreSQL predates GitHub by over a decade. More importantly, the mailing list model forces asynchronous, thoughtful communication. There is no “Merge” button to click impulsively. Every patch must survive public technical scrutiny, and the archives serve as a permanent record of why every design decision was made. Many committers consider this model superior to the PR-based workflow precisely because it raises the bar for both contributors and reviewers.

14.2 Types of Contributions

A common misconception is that “contributing to open source” means writing code. In PostgreSQL, some of the most impactful contributors are people who review patches, triage bugs, or improve documentation. The project has a perpetual shortage of reviewers — submitting a patch is easy compared to the expertise needed to evaluate someone else’s patch for correctness, edge cases, and long-term maintainability.

Documentation

Easiest entry point (but never trivial)
  • Fix typos and unclear explanations
  • Add examples to function documentation (many pg functions have zero examples)
  • Translate to other languages
  • Write tutorials and how-to guides
  • Cross-reference related features that docs currently treat in isolation

Bug Reports

Valuable contribution — quality matters more than quantity
  • Report bugs with minimal reproducible examples (a 5-line SQL script beats a paragraph of prose)
  • Verify and triage existing bug reports (can you reproduce it on HEAD?)
  • Test patches from others on your specific platform/configuration
  • Write regression tests that capture the exact failure scenario

Code Patches

Core contribution — the long game
  • Bug fixes (start small: off-by-one errors, edge cases in error handling)
  • Performance improvements (always include benchmarks)
  • New features (expect 3-6 months of review cycles for anything non-trivial)
  • Code cleanup and refactoring (tread carefully — “cleanup” patches that change behavior are rejected)

Review

Highly valued — arguably the fastest path to recognition
  • Review patches in Commitfest (the backlog is always enormous)
  • Test patches for correctness on your platform and configuration
  • Provide constructive feedback with specific suggestions, not vague criticism
  • Help with code archeology (git blame to explain why something is the way it is)
A senior engineer would say: “Don’t optimize for patch count. Optimize for trust. One well-reviewed, thoroughly-tested patch that a committer can merge with confidence is worth more than ten sloppy patches that waste reviewers’ time. The community remembers both.”

14.3 Finding Your First Contribution

Documentation Fixes

Documentation contributions are the “hello world” of PostgreSQL contribution — but that does not mean they lack impact. Many PostgreSQL functions are documented with formal syntax but zero practical examples. Adding a clear, correct example to a function that thousands of DBAs use daily is a genuine service.
Pro tip for finding documentation gaps: Go to the official PostgreSQL docs website, find a function you use regularly at work, and read the documentation as if you had never used it before. If you are confused, others are too. That confusion is your contribution opportunity.

Good First Issues

Not all TODOs are equal. Some have been there for 15 years because fixing them would require major architectural changes. Start with recent TODOs in areas that are actively being developed — check git log to see if the surrounding code has been touched recently.
Writing tests for uncovered code is one of the highest-value, lowest-risk contributions you can make. It improves project quality, teaches you how the code works, and reviewers appreciate test-only patches because they are easy to review and unlikely to introduce regressions.

14.4 Development Workflow

Step 1: Set Up Mailing List

The mailing list is not just a communication channel — it is the development platform. There is no GitHub Issues page, no Jira board, no Slack workspace. The mailing list is the system of record. Learning to navigate it effectively is as important as learning the code.
Common newcomer mistake: Sending your first email as a patch without ever having participated in discussion. The community values people who demonstrate they understand the project before proposing changes. Reply to existing threads with helpful testing results or thoughtful questions first. Build a trail of signal before asking people to review your code.

Step 2: Create Your Patch

PostgreSQL uses git format-patch, not pull requests. The generated .patch file is attached to your email to the mailing list. This means your commit message is your cover letter — it needs to be clear, complete, and self-contained.
Commit message anatomy: The first line is a summary (under 72 characters, imperative mood: “Add” not “Added” or “Adds”). The body explains what changed and why. The Discussion: tag is a PostgreSQL convention that links to the mailing list thread where the patch was discussed. Without it, committers may not have enough context to evaluate your patch.

Step 3: Test Thoroughly

This is where most first-time contributors underinvest. PostgreSQL reviewers will ask “did you run the full regression suite?” and they will test your patch themselves. If it fails tests you should have caught, you lose credibility that takes months to rebuild.
The --enable-cassert build is non-negotiable for serious contributions. It enables hundreds of internal consistency checks (Assert macros) that are compiled out in production builds. Many subtle bugs — dangling pointers, incorrect catalog state, missed lock acquisitions — are only caught with cassert enabled. If your patch passes make check but fails with cassert, you have a real bug.

14.5 Patch Submission

Email Format

Commitfest Registration


14.6 Responding to Feedback

Common Review Comments

Reviewer says: “Please follow pgindent style”

Updating Your Patch

Patch versioning is crucial in the PostgreSQL workflow. Reviewers track versions (v1, v2, v3…) and expect each new version to address all prior feedback. Submitting a v3 that ignores a comment from the v1 review is a quick way to lose reviewer goodwill.
Version discipline matters. Always increment the version number (v1, v2, v3…) and always summarize the delta from the previous version. Reviewers may be tracking 20+ patches simultaneously — making their job easier is how you get faster reviews. A response like “Updated patch attached, please review” with no changelog is frustrating for reviewers and will slow your patch’s progress.

14.7 Patch Lifecycle

The lifecycle below looks straightforward, but the reality is messier. A patch might bounce between “Needs Review” and “Waiting on Author” five or six times over multiple Commitfests. This is normal — it means the community is taking your patch seriously enough to invest review time. The patches that get rejected outright are often the ones that were never reviewed at all, which typically means they were either too large to review or too poorly motivated to attract interest.
The unwritten social contract: If you submit a patch to Commitfest, you are implicitly agreeing to review at least one or two other patches in the same Commitfest. This is not enforced technically, but the community notices — and contributors who only submit without reviewing tend to get slower reviews over time. Think of it as paying it forward: your patch benefits from the review system, so you should contribute to it.

14.8 Community Etiquette

The PostgreSQL community is famously direct. Reviews can feel blunt if you come from environments where feedback is heavily softened. A reviewer saying “This approach is wrong because X” is not being rude — they are respecting your time by being clear. The harshest feedback is often from the people who care most about the project.

Do’s

  • Be patient: Reviews take time; contributors are volunteers with day jobs
  • Be grateful: Thank reviewers, even for criticism — they spent their unpaid time on your code
  • Be thorough: Complete patches (code + tests + docs) save everyone time and signal professionalism
  • Be responsive: Reply within a few days; stale patches get deprioritized
  • Be humble: Even 20-year PostgreSQL veterans learn from review — so will you
  • Research first: Search the mailing list archives before asking; your question may have a detailed answer from 2009 that is still perfectly relevant
  • Address every point: If a reviewer raises 5 issues, respond to all 5, even if just to say “agreed, fixed in v2”

Don’ts

  • Don’t ping repeatedly: One polite follow-up after 2-3 weeks is appropriate. More than that and you are the person nobody wants to review
  • Don’t argue endlessly: State your technical case clearly, once. If consensus goes against you, accept it gracefully. You can always propose it again in a future release cycle with new evidence
  • Don’t take criticism personally: “This code is incorrect” is about the code, not about you. The separation matters
  • Don’t abandon patches: If life intervenes, email the list saying you are withdrawing the patch. Abandoned patches waste reviewer time and clog the Commitfest queue
  • Don’t submit massive patches: A 5,000-line patch is a review burden. Break it into logical, independently-reviewable pieces — even if the pieces only make sense together
  • Don’t ignore feedback: Submitting v2 without addressing v1 review comments is the fastest way to get your patch permanently ignored

Sample Interactions


14.9 Building Your Reputation

Progression Path

Getting Recognized

  • Conference talks: Submit to PGConf, PGDay events. A talk titled “How I fixed my first PostgreSQL bug” is compelling because it is authentic and approachable.
  • Blog posts: Write about your contribution journey. Document the hard parts — the confusion, the failed attempts, the reviewer feedback that stung but made you better. Honesty resonates more than polished narratives.
  • PostgreSQL Weekly: Get your patches mentioned in community newsletters. The visibility compounds over time.
  • Review consistently: Reviewers are the scarcest resource in the community. A person who reviews 20 patches per Commitfest becomes known faster than someone who submits 5 patches.
  • Mentor others: Help newcomers navigate the process you just learned. The community notices people who invest in its growth.
The reputation trap: Do not contribute to PostgreSQL solely as a resume line item. The community has a finely-tuned radar for people who are performing contribution rather than genuinely engaging. Submit patches because you want to solve a problem, not because you want to say “PostgreSQL contributor” on LinkedIn. The irony is that authentic, sustained engagement is what actually gets noticed — and it shows in interviews when you can speak with genuine depth about an obscure subsystem you spent months understanding.

14.10 Practice: Your First Contribution

1

Find a Documentation Issue

Browse doc/src/sgml/ for unclear function documentation. Pick one function you understand well.
2

Improve the Documentation

Add a clear example, fix unclear wording, or add missing details.
3

Test Your Changes

Build the docs and verify your changes render correctly.
4

Create and Submit Patch

Generate a proper patch file and email it to pgsql-hackers.
5

Register in Commitfest

Add your patch to the current commitfest and wait for review.

14.11 Resources

Developer FAQ

Common questions for new contributors

Submitting a Patch

Official patch submission guide

Reviewing a Patch

How to review others’ patches

Code Style

PostgreSQL coding conventions

Interview Deep-Dive

Strong Answer:I identified a documentation gap in the json_populate_record function — the docs described the syntax but had no example showing how it handles nested JSON objects with NULL fields, which is a common source of confusion based on questions I saw on pgsql-general. I cloned the repository, found the relevant SGML file at doc/src/sgml/func.sgml, and added three examples covering the basic case, the nested-object case, and the NULL-handling edge case.Before submitting, I built the docs locally with make html to verify rendering, ran make check to ensure I had not broken anything, and searched the pgsql-hackers archives to confirm no one had already submitted a similar patch. I generated the patch with git format-patch, wrote a cover email explaining the motivation (linking to two pgsql-general threads where users were confused), and sent it to pgsql-hackers with [PATCH] in the subject line. I registered it in the current Commitfest.The hardest part was the review cycle. My first version was returned with feedback that my examples used features from a newer PostgreSQL version than what the docs target. I had to rewrite the examples to work with the minimum supported version. The second version got a style comment about SGML formatting conventions I had not known about. The third version was accepted. Total elapsed time: about 6 weeks from submission to commit.The non-obvious lesson: even a documentation patch goes through rigorous review. This is why PostgreSQL’s docs are considered the gold standard. The bar is high because the output quality matters — millions of developers read those docs.Follow-up: If you wanted to contribute a code patch to the query optimizer, how would you approach it differently than a documentation patch?The stakes and process are fundamentally different. For a code patch to the optimizer, I would start by spending 2-4 weeks reading the existing code and relevant mailing list discussions to understand the current design philosophy. Before writing any code, I would send an email to pgsql-hackers proposing the change conceptually and asking for design feedback — this avoids investing weeks in an implementation that the community will reject on design grounds. The patch itself would need to include regression tests (not optional for code changes), pass make check under --enable-cassert (assertion-heavy mode), and include performance benchmarks showing the improvement. I would expect 3-6 review cycles spanning multiple Commitfests, and I would need to rebase my patch as other changes land on master. The optimizer is one of the most actively developed subsystems, so merge conflicts are frequent and must be resolved promptly to avoid losing reviewer momentum.
Strong Answer:The core difference is the absence of a “Merge” button. In GitHub-based projects, a single maintainer with write access can review and merge a PR in minutes. In PostgreSQL, a patch must survive scrutiny from multiple reviewers on a public mailing list, be registered in a Commitfest, and ultimately be committed by one of roughly 25 committers who have earned that role over years of demonstrated judgment. There is no way to fast-track a change.The advantages of this model are significant. First, the mailing list creates a permanent, searchable archive of every design decision and its rationale. When someone asks “why does PostgreSQL handle X this way?” five years later, you can find the exact thread where the trade-offs were debated. GitHub PR comments are less discoverable and often lost when PRs are squashed or repos are reorganized. Second, the consensus model means controversial changes get thoroughly aired. The bar for “ready to commit” is not one approving review — it is absence of unresolved objections from the community. This produces more conservative, more stable software. Third, the asynchronous nature of email forces contributors to write clear, self-contained arguments rather than relying on real-time back-and-forth.The disadvantages are real. The barrier to entry is higher — many talented developers are accustomed to GitHub workflows and find the mailing list process intimidating or antiquated. Review latency is measured in weeks, not hours. And the culture can feel opaque to newcomers who do not understand the unwritten norms around patch formatting, thread etiquette, and the Commitfest cadence.My personal view: for a project like PostgreSQL, where correctness is paramount and a bug can corrupt data for millions of users, the mailing-list model’s conservatism is a feature, not a bug. For faster-moving projects where shipping speed matters more than long-term stability, GitHub workflows are more appropriate.Follow-up: If you were advising the PostgreSQL community on one change to make the contribution process more accessible without sacrificing quality, what would it be?I would advocate for a structured “first patch” mentorship program where experienced contributors are explicitly paired with newcomers for their first patch cycle. The technical barrier is not the main obstacle — it is the social barrier of not knowing the norms, not knowing who to CC on an email, not understanding why your patch was silently ignored for three weeks. A mentorship layer would preserve the rigor of the review process while dramatically reducing the drop-off rate of first-time contributors. Some community members have informally done this, but formalizing it with a page on the wiki and explicit opt-in from mentors would signal that newcomer investment is valued at the institutional level.
Strong Answer:I would review in five phases, roughly ordered from cheapest to most expensive to evaluate.First, patch hygiene: Does it apply cleanly against current master? Is it formatted with pgindent? Does the commit message follow conventions (present tense, references to the discussion thread)? These are table stakes — if the patch fails here, I send it back immediately with specific feedback rather than investing time in a deep review.Second, design review: Does the new aggregate function follow the established patterns for aggregate implementation in PostgreSQL? I would check that it uses the standard CREATE AGGREGATE infrastructure, that the state transition function and final function are correctly separated, and that the function handles NULL inputs correctly (most aggregate bugs live in NULL handling). I would also check whether the function could be implemented as a combination of existing functions — adding a new aggregate to core PostgreSQL is a maintenance commitment forever, so it needs to justify its existence.Third, correctness: I would read the C implementation of the state transition function and final function line by line. Key things to check: memory context management (is the aggregate state allocated in the right context so it survives across rows but is freed after the query?), overflow handling for numeric types, and correct behavior for edge cases (empty input, single row, all NULLs). I would also verify that the implementation matches the documented behavior exactly.Fourth, testing: Does the patch include regression tests? Do the tests cover the happy path, NULL inputs, empty input, overflow, and interaction with GROUP BY, HAVING, window functions, and DISTINCT? A common gap: the patch tests the function in isolation but not in combination with other SQL features. I would also check that the expected output file matches actual output by running make check.Fifth, documentation: Is the new function documented in doc/src/sgml/func.sgml? Does the documentation include at least one example? Is the function listed in the appropriate section alongside related aggregates?I would write my review as a reply to the pgsql-hackers thread, organizing feedback by severity: blockers (must fix), suggestions (should consider), and nits (style issues that do not block commit). I would explicitly state my assessment: “Needs revision,” “Ready for committer,” or “Reject” with rationale.Follow-up: The patch author pushes back on one of your review comments, arguing their approach is correct. How do you handle the disagreement?I re-examine my own reasoning first. If I am wrong, I say so immediately and retract the comment — there is no shame in being corrected, and it builds trust. If I still believe I am right, I present a concrete example or test case that demonstrates the problem, rather than arguing in the abstract. If we are genuinely at an impasse on a design question (not a correctness question), I would say “I think this is worth getting more eyes on” and invite other hackers to weigh in. The mailing-list model is designed for exactly this kind of deliberation. I would never block a patch over a matter of taste — only over correctness, safety, or clear precedent violations.
Strong Answer:This is one of the most important judgment calls in PostgreSQL contribution, and getting it wrong wastes months of effort. The core question is: does this feature need to be in the server binary that every PostgreSQL user downloads, or can it live as an installable extension that only interested users opt into?The criteria I use, roughly in priority order:First, does it require core access? Some features fundamentally cannot be extensions because they need access to internal server structures. Changes to the planner, executor, WAL format, or storage engine must be core. If the feature can be implemented using the extension APIs (hooks, custom types, custom indexes, custom functions), it should start as an extension.Second, breadth of applicability. Core features should benefit a large majority of PostgreSQL users. PostGIS is the canonical example of something that is wildly useful but correctly lives as an extension — most PostgreSQL users do not need geospatial queries. Conversely, features like JSONB were added to core because JSON handling is nearly universal in modern applications.Third, maintenance burden. Every line of code in core must be maintained by the committer team indefinitely. A feature that is simple to implement but complex to maintain (many edge cases, frequent bug reports, compatibility constraints across versions) faces a higher bar for inclusion. Extensions shift the maintenance burden to their own developer communities.Fourth, maturity. The PostgreSQL community has a strong preference for features that have been battle-tested as extensions before being proposed for core. This is why many successful core features (like pg_stat_statements, which started as a contrib module) began life as extensions. If your feature has been used in production by multiple organizations as an extension and the community agrees it should be universally available, the path to core is much smoother.Fifth, compatibility guarantees. Core PostgreSQL makes strong backward compatibility promises. Adding a new SQL function to core means that function name is reserved forever. Adding a new GUC (configuration parameter) means it must be supported across major version upgrades. Extensions have more flexibility to break compatibility between versions.My recommendation for any new contributor: start as an extension. It lets you iterate faster, prove the value with real users, and build a track record. If the community later agrees it belongs in core, the existing extension becomes the strongest possible evidence for your proposal.Follow-up: You have built a popular extension with 5,000 GitHub stars. The community is split on whether to bring it into core. How do you navigate that disagreement?I would write a formal proposal email to pgsql-hackers with three sections: (1) the evidence for inclusion — user adoption numbers, performance characteristics, the specific limitation of the extension API that makes core inclusion beneficial; (2) the maintenance commitment I am personally willing to make — because proposing a feature for core without volunteering to maintain it is disrespectful of the committer team’s time; and (3) an honest assessment of the arguments against inclusion, showing that I have genuinely considered the opposing view. Then I would let the thread run, participate in discussion without being defensive, and accept the outcome. If the consensus is “keep it as an extension,” that is a valid answer. Popularity is not sufficient justification — it must also meet the technical criteria. Many of the most successful PostgreSQL ecosystem tools (pgBouncer, pg_repack, Citus before acquisition) thrived as external projects without ever entering core.

Congratulations!

You’re now ready to contribute to PostgreSQL. Remember:
  • Start small: Documentation and bug reports are valuable — they are not “lesser” contributions
  • Be patient: The process takes time but the skills you build (reading unfamiliar C, navigating a large codebase, communicating technical ideas in writing) are career-defining
  • Stay engaged: Consistency matters more than size — one patch per Commitfest for two years builds a reputation
  • Have fun: You’re improving a project used by millions, and you’re joining a community of some of the best database engineers in the world

Next Module

Module 15: Senior Interview Mastery

Ace database questions in senior engineering interviews