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.
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.
┌─────────────────────────────────────────────────────────────────────────────┐│ POSTGRESQL COMMUNITY STRUCTURE │├─────────────────────────────────────────────────────────────────────────────┤│ ││ CORE TEAM (5-7 members) ││ └── Oversees project direction, final authority ││ (Think of these as the "Supreme Court" -- they set precedent ││ and resolve disputes, but rarely write day-to-day code) ││ ││ COMMITTERS (~25 members) ││ └── Can commit code, handle specific areas ││ (Each owns a domain: optimizer, executor, replication, etc. ││ They shepherd patches through and bear responsibility for quality) ││ ││ MAJOR CONTRIBUTORS ││ └── Regular significant contributions ││ (Known by name on the mailing list. Their reviews carry weight.) ││ ││ CONTRIBUTORS ││ └── Anyone who contributes patches, docs, testing ◄── YOU START ││ (Every committer started here. The path is open to anyone.) ││ ││ Communication Channels: ││ ┌─────────────────────────────────────────────────────────────────────┐ ││ │ pgsql-hackers │ Main development discussions (the "town square") │ ││ │ pgsql-general │ User questions (great for understanding pain) │ ││ │ pgsql-bugs │ Bug reports (gold mine for first contributions) │ ││ │ pgsql-docs │ Documentation (lowest barrier to entry) │ ││ │ pgsql-advocacy │ Marketing and promotion │ ││ └─────────────────────────────────────────────────────────────────────┘ ││ ││ Infrastructure: ││ • Git: git.postgresql.org ││ • Mailing lists: lists.postgresql.org ││ • Bug tracker: bugs.postgresql.org ││ • Commitfest: commitfest.postgresql.org ││ • Wiki: wiki.postgresql.org ││ │└─────────────────────────────────────────────────────────────────────────────┘
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.
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
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.”
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.
# Clone the full PostgreSQL source (docs live alongside the code)git clone https://git.postgresql.org/git/postgresql.gitcd postgresql/doc# Find documentation issues -- these are breadcrumbs left by other contributorsgrep -r "TODO" src/sgml/ # Explicit markers for incomplete docsgrep -r "FIXME" src/sgml/ # Known problems waiting for someone to fix# The function docs are the richest target for first contributions# This single file documents ALL built-in SQL functions:# src/sgml/func.sgml (it's enormous -- grep for specific functions)# Build the docs locally to preview your changescd doc/src/sgmlmake html# Open the generated HTML in your browser to verify rendering
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.
# Find TODO comments in source -- these are literally invitations to contributegrep -r "TODO" src/backend/ | head -50grep -r "FIXME" src/backend/ # Known bugs or incomplete implementationsgrep -r "XXX" src/backend/ # "This needs attention" -- a common C convention# Example findings you might see:# src/backend/commands/tablecmds.c:/* TODO: check for pending triggers */# src/backend/optimizer/path/allpaths.c:/* XXX: consider partitionwise join */# Strategy: pick a TODO that is:# 1. In code you can understand (even partially)# 2. Small enough to reason about in a weekend# 3. Has a clear "done" state you can test
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.
Open Bugs
Check: https://www.postgresql.org/list/pgsql-bugs/Look for:• Bugs with minimal reproducers• Issues in areas you understand• Bugs that have been confirmed but not fixed• Old bugs that might have been fixed in recent commits
Commitfest Needs Review
Check: https://commitfest.postgresql.org/Filter by:• Status: "Needs Review"• Author: Anyone (avoid your own)• Target: Current or next releaseEven reviewing and testing counts as contribution!
Missing Tests
# Find untested code paths using code coverage analysis./configure --enable-coverage # Enable GCC/Clang coverage instrumentationmake check # Run existing test suitemake coverage-html # Generate HTML coverage report# Look for red (uncovered) lines in:# htmlcov/src/backend/*/index.html# Focus on:# - Error handling paths (often untested because they're hard to trigger)# - Edge cases in type conversion functions# - Boundary conditions in aggregate functions (empty input, NULL input, overflow)
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.
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.
1. Go to https://lists.postgresql.org/2. Subscribe to pgsql-hackers (for patches -- this is the "main stage")3. Subscribe to pgsql-general (for user context -- understand what frustrates users)4. Read archives to understand culture and expectations (Pay attention to HOW committers give feedback -- their style is your template)5. Lurk for at least 2-4 weeks before posting (This is not optional. The community takes etiquette seriously, and lurking teaches you the norms faster than any guide can.)
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.
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.
# Always start from the latest master -- stale patches create unnecessary conflictsgit checkout mastergit pull origin master# Create a feature branch (local only -- you never push to postgresql.org)git checkout -b my-feature# Make your changesvim src/backend/commands/myfile.c# Commit with a message that tells the FULL story# The PostgreSQL community has strong conventions here:git commit -m "Add feature X to command YThis patch adds support for X when using command Y.Previously, users had to manually do Z, which was error-prone.The implementation adds a new option to the Y command thatperforms Z automatically. No changes to existing behavior.Discussion: https://postgr.es/m/MESSAGE-ID"# ^^^^ This "Discussion:" link ties the patch to the mailing list thread.# It is REQUIRED for non-trivial patches. Committers use it to read context.# Generate the patch file (this is what you email)git format-patch master --stdout > my-feature.patch
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.
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.
# Full regression test -- this is your minimum bar before submittingmake check# Run specific test suites (faster during development iteration)make check TESTS="select insert update"# Isolation tests -- critical if your patch touches anything concurrent# (locks, transactions, MVCC, shared buffers, etc.)make check -C src/test/isolation# Run your own new tests to verify they passmake check TESTS="my-new-test"# Build with assertions enabled -- this catches memory errors and# invariant violations that normal builds silently ignore./configure --enable-cassertmake check# If you can, test on multiple platforms# The Buildfarm (buildfarm.postgresql.org) will catch platform-specific# issues eventually, but catching them yourself shows thoroughness# Priority: Linux (primary), macOS, Windows (frequently breaks)
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.
To: pgsql-hackers@lists.postgresql.orgSubject: [PATCH] Add feature X to command YHi hackers,Attached is a patch that adds support for X when using command Y.== Background ==Currently, when users want to do Z, they need to manually perform steps A, B, and C. This is error-prone because [reasons].== Solution ==This patch adds a new option '--foo' to the Y command that automatically handles Z.== Usage Example == $ pg_dump --foo mydb > backup.sql== Compatibility ==This patch is backward compatible. Existing scripts continue to work.== Testing ==- Added regression tests in src/test/regress/sql/pg_dump.sql- Tested on Linux x86_64 with PostgreSQL master- make check passes== Open Questions ==1. Should --foo be the default in v18?2. Is the error message clear enough?Please review!-- Your Name[Attach: v1-0001-Add-feature-X-to-command-Y.patch]
1. Go to https://commitfest.postgresql.org/2. Click "Add Entry"3. Fill in: - Name: "Add feature X to command Y" - Topics: Choose relevant area - Authors: Your name and email - Reviewers: Leave empty (others will pick up) - Thread URL: Link to your pgsql-hackers email4. Submit and wait for review
# Run pgindent on your filesrc/tools/pgindent/pgindent src/backend/commands/myfile.c# Common issues:# - Tabs vs spaces (use tabs)# - Line length (< 80 chars)# - Brace style (K&R for functions)# - Comment style (/* ... */ not //)
Reviewer says: “Needs regression tests”
-- Add to src/test/regress/sql/mytest.sql-- Test normal caseSELECT my_new_function(1, 2);-- Test edge casesSELECT my_new_function(NULL, 2);SELECT my_new_function(1, NULL);-- Test error casesSELECT my_new_function(-1, 2); -- should error
Reviewer says: “Please document the new option”
<!-- Add to doc/src/sgml/ref/pg_dump.sgml --><varlistentry> <term><option>--foo</option></term> <listitem> <para> Enable automatic Z handling. When this option is specified, the dump will include additional metadata for feature X. </para> </listitem></varlistentry>
Reviewer says: “Have you considered approach B instead?”
Response format:Hi [Reviewer],Thanks for the review!> Have you considered approach B instead?I did consider B, but chose A because:1. [Technical reason]2. [Performance reason]3. [Compatibility reason]That said, I'm open to changing if the consensus prefers B.What do others think?-- Your Name
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.
# Make the requested changesvim src/backend/commands/myfile.c# Commit -- amend if it's a single logical change, new commit if complexgit add -Agit commit --amend # Squash into original for clean patch# Generate new patch with version number in the filename# The "v2" prefix tells reviewers this is an updated patchgit format-patch master --stdout > v2-my-feature.patch# Reply to the SAME thread (do not start a new thread!)# In your reply, summarize what changed since v1:# "Changes in v2:# - Fixed pgindent style issues (per Tom's feedback)# - Added regression test for NULL input case# - Updated SGML docs for new option"
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.
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.
┌─────────────────────────────────────────────────────────────────────────────┐│ PATCH LIFECYCLE │├─────────────────────────────────────────────────────────────────────────────┤│ ││ SUBMITTED ──▶ NEEDS REVIEW ──▶ WAITING ON AUTHOR ──▶ READY FOR COMMITTER ││ │ │ │ │ ││ │ ▼ ▼ ▼ ││ │ (feedback) (you respond) COMMITTED ││ │ │ │ │ ││ │ └────────────────-┘ │ ││ │ │ ││ └──────────────────────────────────────────────────────▶ REJECTED ││ ││ Timeframes (set expectations accordingly): ││ • Initial review: 1-4 weeks (shorter if you review others' patches too) ││ • Iteration: 1-2 weeks per round ││ • Commit: depends on release schedule and committer bandwidth ││ • Total: 1-6 months for non-trivial patches ││ • Major features: 1-3+ years (partitioning took multiple release cycles) ││ ││ Commitfest schedule: ││ • January, March, July, September, November ││ • Each runs for ~1 month ││ • Your patch gets reviewed during CF ││ • Submit before a CF opens for the best chance of timely review ││ │└─────────────────────────────────────────────────────────────────────────────┘
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.
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.
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
> I don't think we need this feature. Users can already do X.Thanks for the feedback. I see your point about X.However, I think this is still valuable because:1. The current workaround requires 3 steps2. It's error-prone (see bug #1234)3. Other databases have this built-inWould it help if I showed some user requests from the mailing list?If the consensus is against, I'm happy to withdraw the patch.I appreciate you taking the time to review!-- Your Name
Year 1:├── Review 10+ patches (easier than writing)├── Submit 2-3 doc fixes├── Fix 1-2 small bugs└── Attend PGConf (virtual or in-person)Year 2:├── Regular reviews (become known)├── Submit minor features├── Write blog posts about PostgreSQL internals└── Help newcomers on mailing listsYear 3+:├── Tackle larger features├── Get nominated for contributor awards├── Become go-to person for specific area└── Potentially become a committer
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.
You say you have contributed to PostgreSQL. Walk me through the lifecycle of your patch -- from identifying the problem to getting it committed. What was the hardest part?
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.
How does the PostgreSQL development process compare to a typical GitHub-based open-source project? What are the trade-offs of mailing-list-driven development?
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.
You are reviewing a patch in the PostgreSQL Commitfest that adds a new aggregate function. What specific things would you check, and in what order?
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.
How would you evaluate whether a specific feature should be contributed to PostgreSQL core versus maintained as an extension? What criteria would you use?
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.
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