Skip to content

docs: slim README and add docs/ tree for v0.1#59

Merged
NikolayS merged 23 commits intomainfrom
docs/v01-restructure
Apr 18, 2026
Merged

docs: slim README and add docs/ tree for v0.1#59
NikolayS merged 23 commits intomainfrom
docs/v01-restructure

Conversation

@NikolayS
Copy link
Copy Markdown
Owner

Summary

Splits the 494-line READMEinto a slim landing page (280 lines) and a flat docs/ tree. Keeps the README focused on what-is-this-why-should-I-care-how-do-I-try-it; moves the long-form material into dedicated files. Resolves the BETTER_DOCS design doc (#49) at v0.1 scope — the full Diátaxis tree with per-quadrant subdirectories is deferred to v1.0 when there is enough content to justify it.

Approach

Dispatched four parallel doc-writer subagents with non-overlapping file ownership, then a style-review pass across all new/changed files, then integration (benchmarks move, docs/README.md index, CLAUDE.md layout pointer, cross-link verification).

What ships

New files under docs/

  • docs/tutorial.md (344 lines) — 9-step order-processing walkthrough. Surfaces the ticker teaching moment (empty receiveforce_tick + ticker → batch). Exercises send/receive/ack, nack-to-retry, max-retries-to-DLQ, observability, and pg_cron switchover. Verified every SQL snippet against sql/pgque.sql.
  • docs/reference.md (475 lines) — per-function reference for the v0.1 default install. Grouped: publishing, consuming, queue management, lifecycle, observability, DLQ, PgQ primitives, trigger helpers, message type, roles, experimental.
  • docs/examples.md (85 lines) — short patterns: send-with-type, batch, fan-out, exactly-once, recurring jobs, DLQ inspection. Relocated from the README's "Usage examples" section.
  • docs/benchmarks.md (29 lines) — throughput table and methodology. Relocated from the README's "Benchmarks" section.
  • docs/README.md (24 lines) — one-page index of the docs/ directory.

Slimmed README.md

  • Removes the inlined function reference table (→ docs/reference.md).
  • Removes the usage examples section (→ docs/examples.md).
  • Collapses Architecture from a 7-bullet list to one paragraph linking to blueprints/SPECx.md and docs/pgq-concepts.md.
  • Adds a Docs section near the top with links to each doc.
  • Adds a hero-image placeholder under the tagline (for the benchmark visual).
  • Fixes style-review findings: PostgreSQLPostgres in prose (badges, URLs, extension names, and DSN schemes preserved); promotional Just/just removed; psql command-line examples now include --no-psqlrc and PAGER=cat.

Blueprint/config updates

  • blueprints/PHASES.md now lists the full v0.1 shipped surface (queue management, observability, PgQ primitives, trigger helpers, roles) — previously claimed only a 9-function minimal list that hadn't kept up with what sql/pgque.sql actually exports.
  • CLAUDE.md gets the docs/ tree added to the file organization map, plus PHASES.md and typescript/ entries for accuracy.

Bugs found during the audit (fixed in-place)

  • set_queue_config parameter naming — callers pass the short name ('max_retries'), not the full column name ('queue_max_retries'). The function auto-prefixes queue_ internally, so 'queue_max_retries' silently becomes queue_queue_max_retries and hits the allowlist rejection. Tests use the correct form; my own PHASES.md draft and blueprints/SPECx.md:2486 both said the wrong thing. Both fixed.

Drift corrected in the old README's function-reference table

Independently surfaced by the reference writer and tutorial writer:

  • status() return type was setof record in the old table; actual is table(component text, status text, detail text).
  • send_at was listed under Publishing; it's experimental, not in the default install. Moved to docs/reference.md's experimental section.
  • ticker() has three overloads shipped (0-arg, 1-arg, 4-arg external-ticker); only the 0-arg was documented.
  • maint() description claimed it does rotation; it skips rotation step 2 (scheduled separately by start()). Clarified.

Not in this PR (intentional)

  • The pre-existing Title-Case headings and PostgreSQL-in-prose slips in CLAUDE.md (8 headings + 4 prose instances) — pre-date this PR; fixing them here would balloon scope. Recommend a small separate style cleanup.
  • Client library per-file docs (clients/*/README.md) — out of scope for v0.1 core docs.
  • Per-quadrant docs/{tutorial,howto,reference,explanation}/ subdirectories — deferred to v1.0 when content justifies it.

Test plan

  • Every SQL snippet in docs/tutorial.md verified against sql/pgque.sql.
  • Every function entry in docs/reference.md verified against sql/pgque.sql.
  • All cross-links resolve (README ↔ docs/ ↔ blueprints/).
  • Style-review pass flagged findings; scoped fixes applied.
  • CI (docs-only PR, no SQL changes — should be clean).
  • make all / benchmark bench rerun is not triggered; no SQL changed.

🤖 Generated with Claude Code

NikolayS pushed a commit that referenced this pull request Apr 17, 2026
Review: #59

Hero image at the top of README — death_spiral.gif illustrating the
failure mode SKIP LOCKED queues hit under sustained load, which PgQue
avoids by construction.

Functional review fixes (real breakages discovered by running the SQL):

- tutorial Step 7 and Step 8: `pgque.maint()` → `pgque.maint_retry_events()`.
  maint() delegates to maint_operations(), which does NOT include retry
  events. As written, the tutorial silently produced 0 rows at the retry
  lesson. In production, pgque.start() schedules maint_retry_events on
  its own cadence.
- tutorial Step 5: corrected force_tick output. create_queue seeds tick
  1, so force_tick returns 1 on the first call (not null as previously
  stated).
- reference.md uninstall grant: previously claimed "superuser only".
  Reality: explicitly revoked from pgque_admin, but PUBLIC execute is
  NOT revoked by default — any connect-privileged role can call it and
  drop the schema. Tightened the wording to match reality and point at
  the revoke command users can run. A follow-up PR will add the revoke
  to the default install so the docs claim becomes automatically true.
- README roles table: same uninstall correction.

DevRel review fixes (clarity + onboarding):

- tutorial Step 1: list `cd /path/to/pgque` and explicit psql prereq so
  `\i sql/pgque.sql` resolves for readers who cloned and ran psql from
  elsewhere.
- tutorial intro: disclaim that sample msg_id / ev_id numbers in
  expected output won't match reality — every force_tick skips the
  event sequence forward by ~1000.
- tutorial Step 7: promoted the "both nack AND ack are needed on the
  same batch" explanation to a bolded callout (DevRel flagged this as
  the single most useful mental-model sentence in the tutorial).
- tutorial Step 8: spelled out the iteration count (two more cycles
  from the Step 7 end-state, given max_retries=2 and retry_count=1).
- examples.md fan-out: new consumers start from the latest tick; the
  old snippet subscribed and immediately called receive on a pristine
  queue, which returned 0 rows. Added explicit send + force_tick +
  ticker after the subscribes.
- docs/README.md: promoted pgq-concepts.md to the user section (the
  tutorial already links it for vocabulary; labeling it
  contributor-only was dissonant).
- README roles block: added "-- replace with a real password" comments
  so copy-paste doesn't land a literal three-dot password.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NikolayS pushed a commit that referenced this pull request Apr 17, 2026
pgque.uninstall() was revoked from pgque_admin, but PUBLIC execute was
left at the PostgreSQL default for SECURITY DEFINER functions. Any role
that could connect to the database could call pgque.uninstall() and
drop the entire pgque schema. The README and docs/reference.md both
claimed the function was "superuser only"; reality was that every
login role had it.

Add `revoke execute on function pgque.uninstall() from public;` in
sql/pgque-additions/roles.sql alongside the existing pgque_admin
revoke. Rebuild sql/pgque.sql. Extend tests/test_pgque_roles.sql to
assert that pgque_admin, pgque_writer, and pgque_reader all lack
execute on uninstall() — catches any future regression.

Found during the functional review of PR #59 (docs restructure). The
docs PR tightened the wording to match pre-fix reality and pointed at
this PR as the follow-up hardening; once this merges, the docs claim
becomes true by default.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NikolayS added a commit that referenced this pull request Apr 18, 2026
pgque.uninstall() was revoked from pgque_admin, but PUBLIC execute was
left at the PostgreSQL default for SECURITY DEFINER functions. Any role
that could connect to the database could call pgque.uninstall() and
drop the entire pgque schema. The README and docs/reference.md both
claimed the function was "superuser only"; reality was that every
login role had it.

Add `revoke execute on function pgque.uninstall() from public;` in
sql/pgque-additions/roles.sql alongside the existing pgque_admin
revoke. Rebuild sql/pgque.sql. Extend tests/test_pgque_roles.sql to
assert that pgque_admin, pgque_writer, and pgque_reader all lack
execute on uninstall() — catches any future regression.

Found during the functional review of PR #59 (docs restructure). The
docs PR tightened the wording to match pre-fix reality and pointed at
this PR as the follow-up hardening; once this merges, the docs claim
becomes true by default.

Co-authored-by: Nik Samokhvalov <nik@niks-mbp.lan>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NikolayS pushed a commit that referenced this pull request Apr 18, 2026
Convert the three production-failure citations (Brandur/Heroku,
PlanetScale, River issue #59) from inline prose to a Markdown list.
Makes each citation scannable on its own line, matching the style
used elsewhere in the README for multi-link lists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NikolayS pushed a commit that referenced this pull request Apr 18, 2026
Bring in the 421-line documentation design doc that was proposed in
PR #49 but never merged. v0.1 docs (this PR, #59) shipped a FLAT docs/
layout — not the full four-quadrant Diátaxis tree that the design doc
proposed. Rather than leaving the thinking orphaned on an unmerged
branch, land it in blueprints/ with a status banner clarifying:

- What v0.1 actually shipped (flat docs/ with six files).
- That the original four-quadrant tree and ten how-to files remain a
  roadmap target for v1.0+ when the content base justifies the split.
- Pointer to PHASES.md and README for what is true today.

Closes the gap between the design doc (in blueprints/) and the
implementation (in docs/ and README.md). PR #49 becomes redundant and
can be closed with a link to this commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Nik Samokhvalov and others added 22 commits April 17, 2026 21:12
Splits the 494-line landing-page-plus-reference-plus-explainer README into
a slim landing page (280 lines) and a flat docs/ tree. Keeps the README
focused on what-is-this-why-should-I-care-how-do-I-try-it; moves the
long-form material into dedicated files.

New docs (flat layout, not Diátaxis — content is thin enough that
quadrant subdirectories would be ceremony):

- docs/tutorial.md — 9-step order-processing walkthrough; surfaces the
  ticker teaching moment (empty receive → force_tick + ticker → batch)
- docs/reference.md — per-function reference for the v0.1 default
  install; 475 lines grouped by category (publishing, consuming, queue
  management, lifecycle, observability, DLQ, PgQ primitives, trigger
  helpers, message type, roles, experimental)
- docs/examples.md — short patterns (send-with-type, batch, fan-out,
  exactly-once, recurring jobs, DLQ inspection), relocated from the
  README's "Usage examples" section
- docs/benchmarks.md — the throughput table and methodology, relocated
  from the README's "Benchmarks" section. README keeps a one-paragraph
  pointer; a benchmark hero image placeholder lives at the top
- docs/README.md — one-page index of the docs/

README changes:

- removes the inlined function reference table (→ docs/reference.md)
- removes the usage examples section (→ docs/examples.md)
- collapses the Architecture bullet list into one paragraph linking to
  SPECx.md and docs/pgq-concepts.md
- adds a Docs section near the top with links to each doc
- adds a hero-image placeholder under the tagline
- fixes style-review findings: "PostgreSQL" → "Postgres" in prose
  (exceptions preserved: badges, URLs, extension names, DSN schemes),
  promotional "Just"/"just" removed, psql command-line examples now
  include --no-psqlrc and PAGER=cat

Other corrections surfaced by the audit and doc-writer agents:

- PHASES.md: lists the full v0.1 shipped surface (queue management,
  observability, PgQ primitives, trigger helpers, roles) — was
  previously claiming only a 9-function minimal list
- PHASES.md + SPECx.md:2486: fix set_queue_config parameter naming
  (callers pass 'max_retries', not 'queue_max_retries' — the function
  auto-prefixes 'queue_' internally; tests already used the correct form)
- CLAUDE.md: adds docs/ tree to the file organization map, adds
  PHASES.md and typescript/ client entries

Tutorial and reference writers independently confirmed drift in the old
README function reference:

- status() return type was setof record; actual is
  table(component text, status text, detail text)
- send_at was listed under Publishing; it is experimental, not in the
  default install
- ticker() has three overloads; only 0-arg was documented
- maint() description claimed it does rotation; it skips rotation step 2
  (scheduled separately by start())

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Review: #59

Hero image at the top of README — death_spiral.gif illustrating the
failure mode SKIP LOCKED queues hit under sustained load, which PgQue
avoids by construction.

Functional review fixes (real breakages discovered by running the SQL):

- tutorial Step 7 and Step 8: `pgque.maint()` → `pgque.maint_retry_events()`.
  maint() delegates to maint_operations(), which does NOT include retry
  events. As written, the tutorial silently produced 0 rows at the retry
  lesson. In production, pgque.start() schedules maint_retry_events on
  its own cadence.
- tutorial Step 5: corrected force_tick output. create_queue seeds tick
  1, so force_tick returns 1 on the first call (not null as previously
  stated).
- reference.md uninstall grant: previously claimed "superuser only".
  Reality: explicitly revoked from pgque_admin, but PUBLIC execute is
  NOT revoked by default — any connect-privileged role can call it and
  drop the schema. Tightened the wording to match reality and point at
  the revoke command users can run. A follow-up PR will add the revoke
  to the default install so the docs claim becomes automatically true.
- README roles table: same uninstall correction.

DevRel review fixes (clarity + onboarding):

- tutorial Step 1: list `cd /path/to/pgque` and explicit psql prereq so
  `\i sql/pgque.sql` resolves for readers who cloned and ran psql from
  elsewhere.
- tutorial intro: disclaim that sample msg_id / ev_id numbers in
  expected output won't match reality — every force_tick skips the
  event sequence forward by ~1000.
- tutorial Step 7: promoted the "both nack AND ack are needed on the
  same batch" explanation to a bolded callout (DevRel flagged this as
  the single most useful mental-model sentence in the tutorial).
- tutorial Step 8: spelled out the iteration count (two more cycles
  from the Step 7 end-state, given max_retries=2 and retry_count=1).
- examples.md fan-out: new consumers start from the latest tick; the
  old snippet subscribed and immediately called receive on a pristine
  queue, which returned 0 rows. Added explicit send + force_tick +
  ticker after the subscribes.
- docs/README.md: promoted pgq-concepts.md to the user section (the
  tutorial already links it for vocabulary; labeling it
  contributor-only was dissonant).
- README roles block: added "-- replace with a real password" comments
  so copy-paste doesn't land a literal three-dot password.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the hero gif with an updated version (same 900x700
dimensions; new animation). README markup is unchanged — img src
path and width stay the same.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Swaps the order of the tagline / badges / hero image block so the
badge row sits directly under the tagline and the gif anchors the
landing area below. Matches the convention most readers scan top-down.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wraps the tagline and badge strip in <p align="center"> blocks so they
match the centered hero gif below. Converts the badge Markdown to the
equivalent <a><img></a> HTML because <p align="center"> does not pass
layout through to nested Markdown image-link shortcuts on GitHub.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace "No extensions. No daemon. One SQL file." with
"\i to install, pg_cron to tick."

pg_cron is a C extension that ships as a background worker on Postgres.
Saying "no extensions" and "no daemon" in the tagline glossed over the
default-path requirement. The new tagline states the actual workflow in
the same number of beats and survives review.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Switches the Markdown `# PgQue…` heading to `<h1 align="center">` so
the title lines up with the centered tagline, badges, and hero gif
below.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
psql meta-command is confusing for readers who do not use psql every
day. "One SQL file to install" is universal and restores the punch of
the original tagline without overpromising.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-locked wording

- Add Aurora to the managed-provider list alongside RDS / Cloud SQL /
  AlloyDB / Supabase / Neon.
- Convert the two historical-context deck links from inline prose to a
  Markdown bullet list.
- "Most Postgres queues rely on SKIP LOCKED plus DELETE or UPDATE"
  becomes "DELETE and/or UPDATE" — most SKIP LOCKED queues do both.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the "lost art / database kung fu" framing with the actual
technical reason PgQue exists: standard PgQ ships as a C extension
plus a pgqd daemon, both unavailable on most managed Postgres
providers, and PgQue rebuilds the engine in pure PL/pgSQL to close
that gap.

Keeps the "another distributed system in your stack" argumentative
beat and the "battle-tested" framing (earned by citing Skype history).
Drops the "kung fu" / "lost art" flourishes that some readers
(especially senior infra people) bounce off. Managed-provider list
stays in the anti-extension paragraph immediately below — no need to
list them twice.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two fixes:

1. Name the latency explicitly — "end-to-end delivery latency" (the
   producer-to-consumer visibility gap), not just "delivery". The old
   wording was ambiguous and could be read as PgQue being slow at
   per-call SQL, which benchmarks contradict (consumer read rate
   ~2.4M ev/s, per-call send/receive/ack are microseconds). Add a
   sentence making this distinction explicit and link to benchmarks.

2. Drop the LISTEN/NOTIFY mention. The emit side is wired in the
   ticker, but LISTEN does not work under transaction-mode pooling
   (PgBouncer, RDS Proxy), which is common on managed Postgres — our
   target audience. Advertising a wake-up path that silently doesn't
   work for half that audience is worse than not advertising. A
   follow-up PR will either gate the pg_notify emit behind an opt-in
   config or disable it for v0.1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Convert the three production-failure citations (Brandur/Heroku,
PlanetScale, River issue #59) from inline prose to a Markdown list.
Makes each citation scannable on its own line, matching the style
used elsewhere in the README for multi-link lists.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a shell-side alternative to the in-psql `\i` install. Uses
`psql --single-transaction -f sql/pgque.sql` so readers who prefer
running from a shell script or CI step get the same single-transaction
guarantee without having to enter psql interactively.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Move pg_cron from "optional and recommended" to a real requirement
  for the default ticker setup (matches the tagline "pg_cron to tick").
- Note that pg_cron is pre-installed or one-command available on all
  major managed Postgres providers; link citusdata/pg_cron setup guide
  for self-managed installs.
- New "pg_cron in a different database" subsection — pg_cron jobs run
  in the cron.database_name database, so if PgQue lives elsewhere the
  user needs cron.schedule_in_database. Link the citusdata cross-DB
  pattern and record it as a todo for pgque.start() to detect
  automatically.
- Manual-ticker fallback stays for users without pg_cron at all.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Tighten the Requirements line so it does not imply pg_cron is a hard
dependency. The real requirement is "something that calls
pgque.ticker() periodically"; pg_cron is the default recommendation
because it is available on every major managed provider, but any
external scheduler works. Keeps the setup guide link and the
manual-ticker fallback already documented below.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PgQue has no 1.0.0-dev release; the version string is assembled by
build/transform.sh and varies per build. Replace the literal with
"[[your version]]" placeholders in the tutorial's two sample outputs
and rewrite the reference's parenthetical so it doesn't claim a
specific string.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bring the tutorial's "Next steps → Production cadence" subsection up
to the same level of pg_cron guidance as README:

- Note that pg_cron is pre-installed or one-command available on all
  major managed Postgres providers (RDS, Aurora, Cloud SQL, AlloyDB,
  Supabase, Neon). Link the citusdata setup guide for self-managed.
- New "pg_cron in a different database" paragraph — cross-database
  pattern link and todo for pgque.start() auto-detection.
- "Without pg_cron at all" fallback names concrete alternatives
  (system cron, systemd, worker loop) to match README wording.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… example

New "Monitoring: queue + consumer health" section in docs/examples.md
showing pgque.get_queue_info() and pgque.get_consumer_info() in psql
\x expanded layout. Two snapshots:

- healthy state on the orders/processor queue (ticker_lag < 2 s, lag
  in milliseconds)
- same queue two hours later with a stuck consumer (lag climbed to
  02:15:33, last_seen to 02:14:59, pending_events 847)

The contrast teaches what "healthy" vs. "broken" looks like without
cribbing values from Kukushkin's 2026 Rediscovering PgQ deck. Keeps
the existing red-flag alert list below plus a pointer to status().

PgQ has get_queue_info / get_consumer_info; PgQue inherits both with
identical column names, so the same monitoring surface works
unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two related issues for production users enabling pgque.start():

1. `cron.job_run_details` growth. pg_cron logs every job execution; at
   our 2-second ticker cadence that is ~2,000 rows per hour from PgQue
   alone. Left unchecked the table will dominate the database. Add a
   "pg_cron log hygiene" callout to both README Installation and the
   tutorial's Production cadence section, mirroring the pattern from
   pg_ash: primary recommendation is `alter system set cron.log_run =
   off` (postmaster context, needs restart); fallback is a periodic
   `delete from cron.job_run_details` job. Record a todo for a future
   pgque.start() to warn about this and offer to schedule the purge.

2. The tutorial previously described `pgque_maint` as "(retries,
   cleanup)". Reality: pgque.maint() -> maint_operations() does NOT
   include maint_retry_events. Retry events are not scheduled by
   pgque.start() at all today (tracked as a separate fix PR). Change
   the parenthetical to "(rotation step 1 and vacuum)" so the doc
   matches current behavior instead of the intended behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Functional review round 2 HIGH fixes:

- docs/reference.md: "4 rotation tables" -> "3 rotation tables" (default
  queue_ntables is 3; conflicted with README's "three-table" and
  pgq-concepts.md's "3 rotating tables").
- docs/pgq-concepts.md: remove reference to `pgque.is_batch_done` (does
  not exist in the shipped default install). Reword Cross-DB exactly-
  once entry to describe the pattern without naming a missing helper.
- docs/pgq-concepts.md: stop recommending `pgque.create_queue(name,
  options jsonb)` — that 2-arg overload is experimental
  (sql/experimental/config_api.sql). Route users to
  `pgque.set_queue_config(queue, param, value)` with the short-name
  conventions documented elsewhere. Add max_retries to the tunable
  list.

DevRel polish round 2 — top three plus high-value nits:

- README framing paragraph: drop "ever built" (unanchored superlative),
  "1-billion-user scale" (Skype peak was ~300M concurrent users)
  -> "hundreds of millions of users", "very large" and "for years" ->
  "large" + "over a decade". Drop "same" from "that same battle-tested
  engine" (redundant). Narrow "and every other managed provider" to
  "most other managed providers". Drop repeated "`\i` and go" tagline
  callback. Drop "worth your time" editorializing on the two decks.
- README Why PgQue: drop "quietly" (rhetorical), "over time"
  (redundant with "stays predictable"). Rename "abuse" to "sustained-
  load regime" (colloquial -> technical). De-echo "paying ... tax
  ... pay".
- README Latency trade-off: "probably the wrong hammer" ->
  "the wrong tool", "that's exactly where it gets interesting" ->
  "that is where PgQue fits".
- README Comparison: "What genuinely differentiates" -> "What
  differentiates", "structurally" -> "by design", "fundamentally
  different" -> "different". Split the comma-spliced "no tuning,
  immune to xmin horizon pinning" into two assertions.
- README Project status: drop "very large" + "over many years" stack
  ("battle-tested at Skype scale for over a decade" is tighter) and
  "intentionally" (redundant with the doc's deliberate voice).
- Tutorial Step 7 and Step 8: fix voice drift ("we" -> "you") — the
  rest of the tutorial is strict second person.
- docs/examples.md exactly-once: de-repeat "roll back ... roll back
  ... roll back".
- docs/benchmarks.md key takeaways: "sustained ... sustained" -> one
  "sustained", "hard" -> "sharply", "You keep Postgres guarantees" ->
  "Full Postgres guarantees" (match the other bullets' noun-phrase
  form).

Deferred: the remaining ~40 DevRel nits (paragraph-level rewrites,
section ordering, cross-doc vocabulary alignment) that are smaller
wins than the batch above.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Replace docs/images/death_spiral.gif with the newer version from
  Downloads. Same dimensions (900 x 700), same markup in README.
- Apply the benchmarks.md key-takeaways polish that the previous
  commit missed (sustained/sustained de-dupe, "hard" -> "sharply",
  "You keep" -> "Full" to match the other bullets' noun-phrase form).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bring in the 421-line documentation design doc that was proposed in
PR #49 but never merged. v0.1 docs (this PR, #59) shipped a FLAT docs/
layout — not the full four-quadrant Diátaxis tree that the design doc
proposed. Rather than leaving the thinking orphaned on an unmerged
branch, land it in blueprints/ with a status banner clarifying:

- What v0.1 actually shipped (flat docs/ with six files).
- That the original four-quadrant tree and ten how-to files remain a
  roadmap target for v1.0+ when the content base justifies the split.
- Pointer to PHASES.md and README for what is true today.

Closes the gap between the design doc (in blueprints/) and the
implementation (in docs/ and README.md). PR #49 becomes redundant and
can be closed with a link to this commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Brings the docs into line with the rebased main (PR #60 uninstall
revoke), with PR #64's 1-second tick cadence (currently open), and
with the round-3 review findings.

README
- PgQ history paragraph: "installations" -> "deployments", recast the
  em-dash clause so "neither of which run on most managed Postgres
  providers" is unambiguous.
- §Why PgQue: drop "nicely" rhetorical.
- §Latency trade-off: rewrite to separate end-to-end delivery latency
  (~1-2 s: up to 1 s for the next tick + consumer poll) from per-call
  latency (microseconds). Drop the benchmarks link that didn't back
  the per-call claim.
- §Comparison: "position-in-shared-log" -> "a position on a shared
  log". §"When to use PgQue vs. a job queue" — drop the restated
  event/job lead-in line that duplicated the Comparison Notes bullet;
  open with the two bullets directly. "zero-maintenance bloat
  behavior" -> "no bloat to tune around".
- §Installation: every "2 seconds" / "1-2 seconds" -> "every 1 second"
  / "every second". pg_cron log hygiene callout updated with 3,600
  rows/hour number (was two-sentence / vague).
- §Installation closing: "initial setup for now" -> "one-way for now"
  (active voice).
- §Roles: uninstall() wording flipped to reflect main state — revoked
  from both pgque_admin and PUBLIC, superuser-only in the strict
  sense.

docs/tutorial.md
- Step 4 canonical-loop callout (new): voice drift fix ("we have not
  started" -> "you have not started") + every-second cadence.
- Step 2: call out explicitly that any number of producers can write
  to the same queue concurrently, any number of consumers can
  subscribe, and any number of queues can coexist in one database.
- NEW callout after Step 6: "What you just did, in PgQ terms." Maps
  modern receive / ack / nack to PgQ's canonical consumer loop
  (next_batch -> get_batch_events -> event_retry -> finish_batch) and
  names every field in pgque.message alongside its ev_* source. This
  is the foundational path from Kreen's 2009 PgCon talk; the tutorial
  should surface it.
- Step 5 / 9 / Production cadence: every "2 seconds" / "one to two
  seconds" -> "1 second" to match PR #64.
- Step 9 lag / last_seen definitions: reworded to match Kukushkin's
  slide framing (age of last finished batch / elapsed time since
  consumer processed a batch) for consistency with the 2026 deck the
  README links.
- Step 7 broken link fixed: points at pgque.maint() in Lifecycle
  instead of the non-existent maint_retry_events anchor.

docs/reference.md
- §start(): "every 2 s" -> "every 1 s"; "raises" -> "errors" (SQL
  audience, not Python).
- §ticker(): "every ~1-5 s" -> "every 1 s by default" (aligns with
  README and tutorial).
- §uninstall(): grant line flipped — execute revoked from both
  pgque_admin and PUBLIC now that PR #60 is merged into main.

docs/pgq-concepts.md
- Glossary: Queue, Producer, Consumer entries now call out
  unbounded-count (multiple queues per DB, multiple producers per
  queue, multiple consumers per queue with independent cursors). The
  fan-out property is PgQ foundational and was implied but never
  stated in the glossary.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@NikolayS NikolayS force-pushed the docs/v01-restructure branch from 7791d91 to 4a7f576 Compare April 18, 2026 04:21
@NikolayS NikolayS merged commit bf9c035 into main Apr 18, 2026
8 checks passed
@NikolayS NikolayS deleted the docs/v01-restructure branch April 18, 2026 04:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant