Complete setup and usage guides for accessing PostgreSQL mailing lists and repositories.
For LLM clients: see /llms.txt for a structured index of all programmatic interfaces, suitable for autonomous agents that need to bootstrap context about postgr.esq quickly.
postgr.esq offers multiple protocols to access the same data. Choose the one that fits your workflow:
POST /api/graphql — one round trip, multi-inbox queries via aliasingIMAP treats each PostgreSQL mailing list as an IMAP folder. Once connected, you can browse, search, and read messages directly in Thunderbird, Apple Mail, Outlook, or any IMAP-compatible email client.
pgsql-general (most active, general discussion).
1. Click "pgsql-hackers" folder
2. Your email client shows the newest messages first
3. Click a message to read the full thread
1. In Thunderbird: right-click a folder → Search Messages
2. Search for: "VACUUM performance" across pgsql-performance
3. Results show all matching messages with context
1. Set your client to check for new mail every 1 hour (Settings)
2. Enable notifications when new messages arrive
3. You'll get alerts for new pgsql-hackers discussions
POP3 downloads messages and removes them from the server. Use this if you want to keep a local archive of PostgreSQL discussions.
Username format is required and strict. The server replies
-ERR no UUID@ in mailbox name if the <UUID>@
prefix is missing.
deadbeefdeadbeefdeadbeefdeadbeef or
dead-beef-dead-beef-dead-beef-dead-beef.pgsql.hackers,
pgsql.general, pgsql.bugs.anonymous.Example username: deadbeefdeadbeefdeadbeefdeadbeef@pgsql.hackers
Set your client to check every 24 hours. All new messages download and stay on your computer. Good for backup and offline research.
If you use a newsreader (Thunderbird, Usenet clients), connect via NNTP. Each mailing list appears as a newsgroup.
Note: Newsgroup names use hyphens, not dots.
Browse and post to discussions like you would in a classic NNTP newsgroup. Good for developers familiar with that workflow.
Clone any PostgreSQL mailing list as a git repository. Each message is a commit. Use this for data analysis, historical research, or building tools.
What these repositories actually are. The git URLs under /m/<inbox>.git are public-inbox v2 archives of mailing-list traffic. They are not mirrors of the upstream PostgreSQL source tree. Each commit is one email; the working tree contains the message's metadata and body. To clone the actual PostgreSQL source code or any other upstream project repository, go to its canonical home (for PostgreSQL: https://git.postgresql.org/git/postgresql.git). postgr.esq does not re-publish project source repos.
(Shows how many messages per day)
git clone --depth 100 https://postgr.esq/m/pgsql-hackers.gitEvery indexed inbox has a search endpoint at https://postgr.esq/m/<inbox>/?q=<term>. Add &format=json to get JSON instead of the HTML view. Each inbox is also exposed as a public-inbox v2 git repository at https://postgr.esq/m/<inbox>.git.
Note: indexes are populated from upstream archives over time. If you query an inbox that's still importing you'll see “No messages yet.” or “Search is not available for this inbox.” That's import lag, not breakage. Inboxes confirmed populated today include pgsql-announce, pgsql-committers, pgsql-performance.
None. curl, wget, fetch, or any HTTP client.
The endpoint https://postgr.esq/m/<inbox>/?...&format=json accepts these query parameters. You may combine them; results are filtered by the intersection of the supplied predicates. At least one of q, subject, from, mid, after, or before must be present.
| Param | Meaning |
|---|---|
q | Full-text query against subject, from, and body. BM25 by default; treated as a TRE regex if regex=1. |
subject | Filter on the Subject header (BM25). |
from | Filter on the From header (BM25; matches name or address fragments). |
mid | Exact Message-ID match (angle brackets stripped). |
after | YYYY-MM-DD — only messages with Date ≥ this day. |
before | YYYY-MM-DD — only messages with Date < this day. |
regex=1 | Interpret q as a TRE regex (uses pg_tre). URL-encode regex metacharacters. |
k=N | Edit-distance for fuzzy regex (0 = exact, 1+ allows that many typos). Only meaningful with regex=1; capped at 5. |
format=json | Return JSON instead of HTML. |
limit, o | Page size (default 50, max 1000) and offset. |
Returns the total hit count and the first match for “release” in pgsql-announce. Each result has subject, from, date, message_id, thread_url, message_url, and a BM25 relevance score.
Search a different inbox; limit and o (offset) page through results. Drop &format=json to render the same query as a browseable HTML page.
Restrict the BM25 match to the Subject header. Useful when the body is noisy or you only care about announcement-style headlines.
Match a fragment of the From header (display name or address).
Equivalent to fetching the message page directly; convenient when you have a Message-ID from another source and want a JSON record.
Q1 2024 only. after is inclusive, before is exclusive. You can combine date filters with any of the other predicates.
TRE regex via pg_tre. The example matches both “release” and “releaze”. Remember to URL-encode [, ], +, etc.
k=1 tolerates one typo against the regex pattern; useful when subjects vary in spelling. Capped at k=5.
Standard Atom feed of recent messages. Poll no more often than once every 5 minutes — the feed only changes when new mail arrives, and aggressive polling wastes bandwidth on both sides. Most feed readers default to 30–60 minutes, which is appropriate.
Returns the original message bytes, including all headers and the unmodified body. URL pattern is /m/<inbox>/<message-id>/raw. Pipe into your own MIME parser or save to disk for archival.
URL pattern is /m/<inbox>/<begin>-<end>.mbox.gz, where begin and end are public-inbox v2 article numbers. Range is capped at 10000 messages per request. Use this to seed a local mbox archive without cloning the full git repo.
Public-inbox v2 layout. Run your own indexer or mirror locally for offline analysis. (Reminder: this is the mailing-list archive, not upstream PostgreSQL source.)
&format=json.?limit=N&offset=M. Default limit is 200, max enforced server-side.https://postgr.esq/ in a browser to see the full inbox list and pick one.The GraphQL endpoint exposes the same data as the REST API but lets the caller specify which fields they want. Useful when you'd otherwise be making N requests in a loop and stitching JSON together.
Endpoint: POST https://postgr.esq/api/graphql (Content-Type: application/json). GET with a ?query=… parameter also works for read-only queries. There is no /<inbox>/graphql URL — every Query field takes an explicit inbox: String! argument instead.
Interactive explorer: open https://postgr.esq/api/graphql in a browser and you get the GraphiQL UI with schema introspection, autocomplete, and query history. Programmatic clients (curl, fetch with Accept: application/json) keep getting the JSON API as before.
Top-level Query fields:
inbox(inbox: String!) — metadata: name, description, addresses, message count, last-modified.messages(inbox: String!, limit: Int = 25) — recent messages.message(inbox: String!, mid: String!) — one message by Message-ID, including body and attachments.thread(inbox: String!, mid: String!) — full thread rooted at a Message-ID.search(inbox: String!, query: String!, limit: Int = 50, offset: Int = 0) — BM25 search; results carry a relevance score.Returns both the inbox header and the first three search hits in one round trip. Compare with the REST API, which would require two calls.
Replace the mid value with a real Message-ID from the inbox you care about (you can copy one from a REST search response or the HTML view). Add body to the messages selection set if you also want the message text.
errors array. Check both data and errors in your client.inbox argument is required on every field. The endpoint is not scoped to any inbox; the schema deliberately surfaces the inbox name in each query so a single GraphQL request can span multiple inboxes by aliasing.If you're building an AI agent (Claude Code, Kiro, Pi, or any MCP-compatible tool), connect to our MCP server.
Your agent now has 70+ tools available:
Pre-built skills for Claude, Kiro, and Pi available at:
| Use Case | Best Endpoint | Why |
|---|---|---|
| Browse discussions like email | IMAP | Familiar email client, threading, search built-in |
| Download archive to computer | POP3 | Keep local copy, work offline |
| Old-school newsreader fan | NNTP | Classic protocol, powerful newsreaders available |
| Build tools / analyze history | Git | Version control, scripting, full history |
| Quick searches / dashboards | HTTP/REST | Simple API, JSON responses, easy integration |
| AI agent integration | MCP | Purpose-built for AI, structured queries, 70+ tools |
postgr.esq mirrors the University of California, Berkeley POSTGRES
project (1986–1995) — the academic predecessor of
PostgreSQL — at /legacy/. The
upstream archive at dsf.berkeley.edu/postgres.html
has been effectively static since 1999; this mirror exists so the bytes
survive if the upstream ever disappears.
The original UCB POSTGRES hackers list, including design-era discussions from Stonebraker and the original implementors:
/m/ucb-postgres//m/ucb-postgres/?q=stonebraker/m/ucb-postgres/new.atom/legacy/mail-archive/ (64 monthly tarballs plus a single aggregated all-messages.mbox for grep)search_messages(inbox="ucb-postgres", query="vacuum")/legacy/papers/ — both PostScript and ps2ascii text. Includes "Design of POSTGRES", "Implementation of POSTGRES", "Rules, Procedures and Caching", and ten more./legacy/postgres-v4r2/postgres.faq/legacy/postgres-v4r2//legacy/postgres-v4r2/contrib/sha256: /legacy/manifest.json/legacy/upstream-snapshot.htmlThe archive contains the CONCERT Trouble Ticket System (a contrib sample application), not bug tickets — UCB never used a bug tracker for the project. Patch discussions and design exchanges are in the mailing list.
/legacy/extracted/ or grab the tarball /legacy/postgres-v4r2/postgres-v4r2.tar.Z./legacy/oldpost//legacy/oldpost/unofficial-ports/, UNOFFICIAL-PORT-LIST.search_symbols(repository="ucb-postgres-v4r2", query="parser") and git_log(repository="ucb-postgres-v4r2"). The expected repository names are ucb-postgres-{v3r1,v4r0,v4r1,v4r2} and ucb-postgres95-{0.01..1.02}; consult /data for current indexing status.imap.postgr.esq (no www, no .com)pgsql-general?q=query instead of complex syntax+ or %20jq . to see response structuregit clone --depth 10 ...git log -p --max-count=100Every public HTTP endpoint described on this page is also documented in a single OpenAPI 3.1 document — search, single-message JSON, raw RFC 822, threads, Atom/RSS feeds, inbox metadata, the help/color/mirror text pages, the git smart-HTTP transport, /healthz, and the MCP JSON-RPC envelope.
The spec is served by Agora itself at /openapi.yaml and rendered as an interactive Swagger UI page at /api.html. Both are kept in lock-step with the route table in pkg/protocol/http/router.go; if a route is broken (today: the git-upload-pack POST) the spec flags it with x-status: pending rather than pretending it works.
Loads Swagger UI from a CDN and points it at the live spec. Each endpoint has a “Try it out” button that issues real requests against the production service.
Useful for embedding in your own docs site, validating with spectral lint, or generating clients with openapi-generator.
Replace python with any of the supported targets (typescript-fetch, go, rust, etc.). The generated client speaks JSON only — for the HTML, Atom, RSS, and git smart-HTTP routes you still need a regular HTTP client.
&format=json for the JSON envelope. The OpenAPI document only describes the JSON variant.Link headers (RFC 8288 rel="next" / rel="prev" / rel="first") instead of recomputing offsets. The body's has_more is also reliable.POST /mcp/ entry in the spec describes the JSON-RPC envelope. AI agents should use a real MCP client library; the OpenAPI is there mostly for debugging.Something not working as described? Get in touch. We want these endpoints to work perfectly.