Regrets
Edit this pagePosted: 2026-09-08 · Report this thread
Blame claude for the bad ideas. All the good ones were mine though.
| Record | Date | Decision | Status |
|---|---|---|---|
| 0784 | 2026-09-12 | Pages project is recreated as sqlstreams | accepted |
| 0783 | 2026-09-12 | Heartbeats are jittered like ticks | accepted |
| 0782 | 2026-09-12 | sqlstreams.io is the documentation origin | superseded |
| 0781 | 2026-09-12 | A declined claim backs off in the pool, and live instances keep their poll rate | accepted |
| 0780 | 2026-09-12 | The group manager keeps its stream's upkeep and drops the system rows | accepted |
| 0779 | 2026-09-12 | The idle fleet's cost is the manager tick, and its losing claims convoy on the shared system rows | accepted |
| 0778 | 2026-09-12 | The profile effect begins after four idle seconds | accepted |
| 0777 | 2026-09-12 | CLI migration names follow the client | accepted |
| 0776 | 2026-09-12 | The profile text container expands to viewport width | superseded |
| 0775 | 2026-09-12 | The profile effect begins after three idle seconds | superseded |
| 0774 | 2026-09-12 | CLI alert JSON and maintenance durations follow the read contract | accepted |
| 0773 | 2026-09-12 | Profile scroll slowdown is eased slightly | superseded |
| 0772 | 2026-09-12 | Profile scrolling slows as the personal text grows | superseded |
| 0771 | 2026-09-12 | Scheduler concurrency help follows produce validation | accepted |
| 0770 | 2026-09-12 | CLI resource JSON and binding scope follow the client | superseded |
| 0769 | 2026-09-12 | The profile fades while idle and its personal text grows | superseded |
| 0768 | 2026-09-12 | CLI registration, health, and worker reads name their client operations | accepted |
| 0767 | 2026-09-12 | The multistream ladder is retired for unpaced ceiling holds | accepted |
| 0766 | 2026-09-12 | CLI commands mirror client verbs | accepted |
| 0765 | 2026-09-12 | Accept all memes use WebP images | accepted |
| 0764 | 2026-09-12 | Avatar images match their display sizes | accepted |
| 0763 | 2026-09-12 | Header wordmark links home | accepted |
| 0762 | 2026-09-12 | Client imports use the declared package name | accepted |
| 0761 | 2026-09-12 | Repository cleanup preserves records and repairs site links | accepted |
| 0760 | 2026-09-12 | Client package lives at the module root | superseded |
| 0759 | 2026-09-11 | Partition creation runs in an explicit transaction | accepted |
| 0758 | 2026-09-11 | The debug buffer stays always-on at its measured cost | accepted |
| 0757 | 2026-09-11 | Retain per-stream tables instead of LIST/RANGE subpartitioning | accepted |
| 0756 | 2026-09-11 | Accept all wears the dark pattern | accepted |
| 0755 | 2026-09-11 | Benchmark commands and runs use bench | accepted |
| 0754 | 2026-09-11 | Benchmark runs share configuration and output | accepted |
| 0753 | 2026-09-11 | Manager coordinates existing benchmark roles | superseded |
| 0752 | 2026-09-11 | Proposed site pages exist only for features a user consumes | accepted |
| 0751 | 2026-09-11 | Results follow maintained scenario families | accepted |
| 0750 | 2026-09-11 | Benchmarks retain recurring workloads and freeze completed investigations | superseded |
| 0749 | 2026-09-11 | Benchmark runner lives at the .bench root | superseded |
| 0748 | 2026-09-11 | Published throughput uses three fixed-duration runs and retains every outcome | accepted |
| 0747 | 2026-09-11 | Throughput scenarios can disable message recording while retaining aggregate measurements | accepted |
| 0746 | 2026-09-10 | Concurrent lab handlers use independent record files | accepted |
| 0745 | 2026-09-10 | Maximum throughput uses the reliability lab with explicit workload and environment settings | superseded |
| 0744 | 2026-09-10 | Controllers keep dependencies and registration owns declarations | accepted |
| 0743 | 2026-09-10 | Maintenance completion tracking and startup delay are deferred | accepted |
| 0742 | 2026-09-10 | Maintenance settings and operations are separate | superseded |
| 0741 | 2026-09-10 | Vacuum settings follow stream declarations | superseded |
| 0740 | 2026-09-10 | Scheduled key vacuum is opt-in | superseded |
| 0739 | 2026-09-09 | Partial sweep grace applies to every batch | accepted |
| 0738 | 2026-09-09 | Partial message sweeps have a bounded grace period | superseded |
| 0737 | 2026-09-09 | Examples are a visible root and both test trees live in the .tests module | accepted |
| 0736 | 2026-09-09 | Integration tests live in a nested .tests module over testcontainers | accepted |
| 0735 | 2026-09-09 | Idempotency expiry uses timestamp order | accepted |
| 0734 | 2026-09-09 | Janitor probes oldest row before sweeping | accepted |
| 0733 | 2026-09-09 | Claim observations use xid | accepted |
| 0732 | 2026-09-09 | Diagnostic codes use the SQL prefix | accepted |
| 0731 | 2026-09-09 | vulkantest is one published fixture package with a schema per test | superseded |
| 0730 | 2026-09-09 | Tests are pure, database, or e2e, and a database test runs against Postgres itself | superseded |
| 0729 | 2026-09-09 | SQLStreams wordmark ends with an amber semicolon | accepted |
| 0728 | 2026-09-09 | Rename proposal review stays off the live website | accepted |
| 0727 | 2026-09-09 | SQLStreams technical identity follows the product name | superseded |
| 0726 | 2026-09-09 | SQLStreams cutover recreates disposable databases and keeps a temporary docs origin | superseded |
| 0725 | 2026-09-09 | SQLStreams is the project name | accepted |
| 0724 | 2026-09-09 | The metric root is singular | accepted |
| 0723 | 2026-09-08 | Repository support, build-output, and benchmark roots are hidden | accepted |
| 0722 | 2026-09-08 | Repository support and build-output roots are hidden | superseded |
| 0721 | 2026-09-08 | Repository-only roots are hidden | superseded |
| 0720 | 2026-09-08 | End-to-end tests and runnable examples have separate hidden roots | superseded |
| 0719 | 2026-09-08 | Programs under .e2e are e2e tests | accepted |
| 0718 | 2026-09-08 | End-to-end labs and runnable examples have separate roots | superseded |
| 0717 | 2026-09-08 | The OpenTelemetry integration module is otel | accepted |
| 0716 | 2026-09-08 | Tools holds all repository-only developer tooling | superseded |
| 0715 | 2026-09-07 | Throughput work excludes the archived delivery consumer | accepted |
| 0714 | 2026-09-07 | Consumer observations allocate transaction ids before advancing cursors | superseded |
| 0713 | 2026-09-07 | Sustainable throughput keeps both producer and consumer queues bounded | accepted |
| 0712 | 2026-09-07 | Documentation starts with a runnable example and separates progress from delivery outcomes | accepted |
| 0711 | 2026-09-07 | The reliability lab is the benchmark harness, and a benchmark is a scenario | superseded |
| 0710 | 2026-09-07 | Consumer defaults use small batches and responsive polling | accepted |
| 0709 | 2026-09-07 | Topic alerts evaluate every minute | accepted |
| 0708 | 2026-09-07 | Exporter health has a collection scope | accepted |
| 0707 | 2026-09-07 | Export validation checks only export compatibility | accepted |
| 0706 | 2026-09-07 | Portable export validation and read health | superseded |
| 0705 | 2026-09-07 | OTel readers collect from the producer | accepted |
| 0704 | 2026-09-07 | Alert snapshots expose existing evaluation | accepted |
| 0703 | 2026-09-07 | Collector progress uses manager lease history | accepted |
| 0702 | 2026-09-07 | Instance log timestamps follow existing names | accepted |
| 0701 | 2026-09-07 | Worker instance log writes and retention | superseded |
| 0700 | 2026-09-07 | Worker instance history proves lease coverage | accepted |
| 0699 | 2026-09-07 | Alert timing fields are inline | accepted |
| 0698 | 2026-09-07 | All existing alerts share retained history | superseded |
| 0697 | 2026-09-07 | The record tables are produce_record and handler_record | accepted |
| 0696 | 2026-09-06 | The checker drains on the consumer group cursor, and every scenario declares the safety checks | accepted |
| 0695 | 2026-09-07 | Partition alerts calculate retained duration | superseded |
| 0694 | 2026-09-07 | Alert evaluations return explicit states | accepted |
| 0693 | 2026-09-06 | Metrics collection owns alert evidence | accepted |
| 0692 | 2026-09-06 | Alert evaluations carry findings and evidence | superseded |
| 0691 | 2026-09-06 | Compaction options are constructed inline | accepted |
| 0690 | 2026-09-06 | Alert history uses stored message time | accepted |
| 0689 | 2026-09-06 | Alert implementation starts in existing recording | accepted |
| 0688 | 2026-09-06 | Shared alert history evaluation contract | superseded |
| 0687 | 2026-09-06 | The reliability lab is a ledger and a checker, with scenarios written as Go and printed, never parsed | accepted |
| 0686 | 2026-09-06 | History-based pending belongs to the shared alert framework | superseded |
| 0685 | 2026-09-06 | A claim poll reads its snapshot before any transaction and opens the reclaim transaction only on an expired lease | superseded |
| 0684 | 2026-09-06 | Collector progress contract and bounded history | superseded |
| 0683 | 2026-09-06 | Alert pending duration is derived from measurement history | superseded |
| 0682 | 2026-09-06 | Metrics export uses an OTel producer and source-read health | accepted |
| 0681 | 2026-09-06 | The rule files carry no decision citations; the decision map is the index | accepted |
| 0680 | 2026-09-06 | pkg/concurrency is infrastructure and lives under common | accepted |
| 0679 | 2026-09-06 | The doc site splits by page kind: a Reference board, one thread per handle | accepted |
| 0678 | 2026-09-06 | Metrics export distinguishes read success and observation freshness | superseded |
| 0677 | 2026-09-06 | Public API comments state their contract | accepted |
| 0676 | 2026-09-06 | Admin owns orchestration and domains own validation rules and resource reads | accepted |
| 0675 | 2026-09-06 | The message's own time is sent_at | rejected |
| 0674 | 2026-09-06 | Playground examples share handle, instance, and lifecycle patterns | accepted |
| 0673 | 2026-09-06 | The scheduled time is a message_log column on every message | rejected |
| 0672 | 2026-09-06 | Client results remain unnamed | accepted |
| 0671 | 2026-09-06 | Fatal consumption errors stop the session | accepted |
| 0670 | 2026-09-06 | Public surface review retains capabilities and removes shared mutation | accepted |
| 0669 | 2026-09-06 | An index is named for its table then its leading columns | accepted |
| 0668 | 2026-09-06 | A cursor table carries its own id and the owner's id as UNIQUE | accepted |
| 0667 | 2026-09-06 | Every _config table carries created_at and updated_at | accepted |
| 0666 | 2026-09-06 | The payload never reaches a log line or an error | accepted |
| 0665 | 2026-09-06 | Vulkan defines the supported public API | accepted |
| 0664 | 2026-09-06 | Defaults use the normal client API | accepted |
| 0663 | 2026-09-05 | The janitor timeout names cleanup | accepted |
| 0662 | 2026-09-05 | Janitor cleanup steps have separate deadlines | superseded |
| 0661 | 2026-09-05 | The system declaration configures the metrics collector | accepted |
| 0660 | 2026-09-05 | Ensuring a compaction head is one upsert | accepted |
| 0659 | 2026-09-05 | A missing compaction head has a lockable row | superseded |
| 0658 | 2026-09-05 | Built-in alert config names the alert, not its scheduled work | accepted |
| 0657 | 2026-09-05 | The datastore holds Logger and Retry once | accepted |
| 0656 | 2026-09-05 | Search-engine indexing has one path policy | accepted |
| 0655 | 2026-09-05 | Code-page meta descriptions come from code facts | accepted |
| 0654 | 2026-09-05 | The shared layout qualifies document titles | accepted |
| 0653 | 2026-09-05 | Consumer names the public group handle | accepted |
| 0652 | 2026-09-05 | Astro's build emits the canonical sitemap | accepted |
| 0651 | 2026-09-05 | documentation links related mechanisms in context | accepted |
| 0650 | 2026-09-05 | The migration version reads through the client | accepted |
| 0649 | 2026-09-05 | Alerts take the metrics shape and the one registry | accepted |
| 0648 | 2026-09-05 | Metric scope belongs to the diagnostic declaration | accepted |
| 0647 | 2026-09-05 | First-class metrics use one declaration catalog | superseded |
| 0646 | 2026-09-04 | the topic handle carries the message type; a message key is a handle under it | superseded |
| 0645 | 2026-09-03 | Binding is a handle under the group; client lists are bare plurals | accepted |
| 0644 | 2026-09-03 | Public type names state semantic roles | superseded |
| 0643 | 2026-09-03 | One declaration per type, vulkan as the client plus aliases | accepted |
| 0642 | 2026-09-02 | The client's own ConsumerInstance runs the manager beside Consume | accepted |
| 0641 | 2026-09-02 | Run is a per-caller loop; the row is the only arbiter | accepted |
| 0640 | 2026-09-02 | The shared loop re-claims instead of ending | accepted |
| 0639 | 2026-09-02 | The instance target is vocabulary, not a field poked after construction | accepted |
| 0638 | 2026-09-02 | The manager row is gated and Run is shared | accepted |
| 0637 | 2026-09-02 | The pool builder is client-package API | accepted |
| 0636 | 2026-09-02 | The client takes the pool | accepted |
| 0635 | 2026-09-02 | Consume runs the system manager | accepted |
| 0634 | 2026-09-02 | ProduceInTx takes the message | accepted |
| 0633 | 2026-09-02 | The datastore takes the caller's pool | accepted |
| 0632 | 2026-09-01 | The pool sets no search_path | accepted |
| 0631 | 2026-09-01 | Every SQL literal names its schema | accepted |
| 0630 | 2026-09-01 | A Postgres schema is one Vulkan installation | accepted |
| 0629 | 2026-09-01 | "schema" names a Postgres schema and nothing else | accepted |
| 0628 | 2026-09-01 | The table-name functions are public API | accepted |
| 0627 | 2026-09-01 | worker liveness is an alert, not a register-time check | accepted |
| 0626 | 2026-08-31 | newest-wins is the only declaration form | accepted |
| 0625 | 2026-08-30 | one client over the datastore; resources as handles; verbs on the handle | accepted |
| 0624 | 2026-08-30 | the first RegisterTopic stands up the control-plane schema | accepted |
| 0623 | 2026-08-30 | the standard library's uuid package replaces github.com/google/uuid | accepted |
| 0622 | 2026-08-30 | IdempotencyKey is a caller string, resolved to the claim table's UUID | accepted |
| 0621 | 2026-08-30 | a schedule is a producer on a cron expression; "cron job" is renamed "schedule" everywhere | accepted |
| 0620 | 2026-08-30 | a missing-partition heal creates the partition of the sequence's next id and reruns under the retry policy | accepted |
| 0619 | 2026-08-30 | the Message type argument sits on Register, not on NewProducer / NewConsumer | accepted |
| 0618 | 2026-08-30 | the schema version is a message_log column declared by the Message type, not a topic key | accepted |
| 0617 | 2026-08-29 | ordered delivery per key; concurrency values parallel / exclusive / ordered | accepted |
| 0616 | 2026-08-29 | a new group's cursor position: consumergroup.CursorPosition, Head() | accepted |
| 0615 | 2026-08-29 | delivery_log is keyed by its own id, not by attempt | accepted |
| 0614 | 2026-08-29 | handler outcomes by error classification | accepted |
| 0613 | 2026-08-29 | column naming rules | accepted |
| 0612 | 2026-08-29 | the message key is promoted out of compaction | superseded |
| 0611 | 2026-08-29 | table names are `<root>_<kind>` | accepted |
| 0610 | 2026-08-28 | example attribute values on code threads | accepted |
| 0609 | 2026-08-28 | website/VOICE.md: the doc site's prose voice file | accepted |
| 0608 | 2026-08-28 | Playwright covers the editor swap and the initial-JS ceiling | accepted |
| 0607 | 2026-08-28 | the sandbox quiesces before closing its database | accepted |
| 0606 | 2026-08-28 | the doc site's browser support line | accepted |
| 0605 | 2026-08-28 | the member profile page | accepted |
| 0604 | 2026-08-27 | the transition's ready promise is caught at the source | accepted |
| 0603 | 2026-08-27 | the page-failure net ignores browser cancellations | superseded |
| 0602 | 2026-08-27 | doc site mobile pass: two breakpoints, sandbox gated off phones | accepted |
| 0601 | 2026-08-27 | doc site versioning: one live site, frozen deployments per version | accepted |
| 0600 | 2026-08-27 | each consent control gets its own answer, and Accept all gets its own component | accepted |
| 0599 | 2026-08-27 | the cookie notice is the site's privacy note, on its own surface | superseded |
| 0598 | 2026-08-27 | the site notice's full-page face is cut until something needs it | accepted |
| 0597 | 2026-08-27 | website layered error handling | accepted |
| 0596 | 2026-08-26 | the decision records publish as a board | accepted |
| 0595 | 2026-08-26 | spacing token scale: exact values, pixel-value names, one tier | accepted |
| 0594 | 2026-08-26 | initial-payload ceilings are NOT built | rejected |
| 0593 | 2026-08-26 | the night board, chosen from the footer | accepted |
| 0592 | 2026-08-26 | ClientRouter, without persisting the sandbox | accepted |
| 0591 | 2026-08-26 | the sandbox's Postgres is not prefetched | rejected |
| 0590 | 2026-08-26 | a fix substitutes the caller's values | accepted |
| 0589 | 2026-08-25 | a declaration's diagnose part is SQL | accepted |
| 0588 | 2026-08-25 | the compatibility matrix is exported from the gate's own rule | accepted |
| 0587 | 2026-08-24 | sandbox consumers auto-run on their own clocks | accepted |
| 0586 | 2026-08-24 | the sandbox's Tick runs the real consume path, and drift is counted per verb | accepted |
| 0585 | 2026-08-24 | the claim path's snapshot gate proves on PGlite, so the sandbox can tick | accepted |
| 0584 | 2026-08-23 | the site's SQL console runs the library's own SQL in PGlite | accepted |
| 0583 | 2026-08-23 | the doc site is a phpBB-era message board | accepted |
| 0582 | 2026-08-23 | site stack: Astro without Starlight, Svelte 5 islands | accepted |
| 0581 | 2026-08-22 | the doc site documents shipped behavior only | accepted |
| 0580 | 2026-08-22 | Every migration step declares MinCompatibleVersion; the schema gate admits min_compatible_version <= build <= current | accepted |
| 0579 | 2026-08-22 | migration txn steps run under lock_timeout; timeout retries | accepted |
| 0578 | 2026-08-22 | fillfactor audit: adopt nothing, defaults everywhere | accepted |
| 0577 | 2026-08-22 | Worker metadata history is an append-only worker_log | accepted |
| 0576 | 2026-08-22 | CLI --output json | superseded |
| 0575 | 2026-08-22 | Public read-models carry json struct tags | accepted |
| 0574 | 2026-08-22 | Compaction-key deadlock evaluation: no cycles batched, no library retry | accepted |
| 0573 | 2026-08-22 | binding_log retention: the consumer group janitor | accepted |
| 0572 | 2026-08-22 | Append-only is for history tables | accepted |
| 0571 | 2026-08-22 | Per-topic table split rule | accepted |
| 0570 | 2026-08-22 | Topic truth stays on the topic row; history is an append-only log (topic_log, binding_log) | accepted |
| 0569 | 2026-08-21 | Metric declarations join the shared VK registry | superseded |
| 0568 | 2026-08-21 | Summary lines declare and carry a help breadcrumb | accepted |
| 0567 | 2026-08-21 | Stop line as session summary | accepted |
| 0566 | 2026-08-21 | Slow-operation threshold logging | accepted |
| 0565 | 2026-08-20 | logging grows a record pipeline under the Logger seam | accepted |
| 0564 | 2026-08-20 | Repeated Warn/Error suppression in the logging pipeline | accepted |
| 0563 | 2026-08-20 | Coded declarations move to pkg/common/diagnostic | accepted |
| 0562 | 2026-08-20 | Log events carry VK codes from the error registry | accepted |
| 0561 | 2026-08-20 | Logging machinery moves to pkg/common/logging | accepted |
| 0560 | 2026-08-20 | SQL literal owner comments | accepted |
| 0559 | 2026-08-20 | Per-operation debug buffer | accepted |
| 0558 | 2026-08-20 | Logging rule sheet | accepted |
| 0557 | 2026-08-20 | Developer tooling is a dev-only tools/ module | superseded |
| 0556 | 2026-08-20 | Standing walks over plain raise strings | accepted |
| 0555 | 2026-08-20 | Package kinds, the seam law, and worker placement | accepted |
| 0554 | 2026-08-20 | Plain-error construction standard | accepted |
| 0553 | 2026-08-19 | Which errors get codes: the declaration boundary | accepted |
| 0552 | 2026-08-19 | A missing system topic raises migrate.ErrNotRegistered | accepted |
| 0551 | 2026-08-19 | Retry classification is consulted, never encoded; one retry type | accepted |
| 0550 | 2026-08-19 | Structured error anatomy: five parts + recovery, flat codes | accepted |
| 0549 | 2026-08-19 | worker.Definition becomes data; the concrete machines are *Provisioner | accepted |
| 0548 | 2026-08-19 | The receiver letter is the initial of the type's final word | accepted |
| 0547 | 2026-08-19 | Run-side worker structs are named *Instance; the concrete Definition keeps both roles | accepted |
| 0546 | 2026-08-19 | Controller and datastore verbs drop their own domain noun | accepted |
| 0545 | 2026-08-19 | The waterline worker is renamed cursor_advancer; AdvanceWaterline becomes AdvanceCommitted | accepted |
| 0544 | 2026-08-19 | Dead-field pass: two deletions, one exemption | accepted |
| 0543 | 2026-08-19 | Config field order: domain-first, ambient tail | accepted |
| 0542 | 2026-08-19 | Config & options refinement: the three shape decisions | accepted |
| 0541 | 2026-08-19 | examples, bench, and reference become dev-only nested modules | superseded |
| 0540 | 2026-08-19 | Bare sub-consumer constructors: doc fencing, not structural fencing | accepted |
| 0539 | 2026-08-19 | Blank-line convention for function bodies | accepted |
| 0538 | 2026-08-19 | File content ordering convention | accepted |
| 0537 | 2026-08-18 | Every worker kind carries a controller layer | accepted |
| 0536 | 2026-08-18 | MessageOptions is the sanctioned nilable sparse sub-document | accepted |
| 0535 | 2026-08-18 | consumer/base cleanup: pure constructors, symmetric key verbs, RecordMargin | accepted |
| 0534 | 2026-08-18 | The metrics domain's write door is pkg/metrics/producer | accepted |
| 0533 | 2026-08-18 | Field absence is the zero value, never a nil pointer | accepted |
| 0532 | 2026-08-18 | Consumer read-models live with the controller whose verbs return them | accepted |
| 0531 | 2026-08-18 | System-topic and cron-job declarations live in the domain's controller | accepted |
| 0530 | 2026-08-18 | pkg/compaction stays two-layer; MessageRow lives in common | accepted |
| 0529 | 2026-08-17 | One Querier contract; the produce transaction is the one sanctioned crossing | accepted |
| 0528 | 2026-08-17 | pkg/logger, pkg/retry, pkg/errors, pkg/context merge into a flat pkg/common | accepted |
| 0527 | 2026-08-17 | pkg/migrate adopts the three-layer template | accepted |
| 0526 | 2026-08-17 | migrate.Controller is the package's only door; the schema gate reads by id | accepted |
| 0525 | 2026-08-16 | ProduceBatch: one call, N messages, one transaction | accepted |
| 0524 | 2026-08-16 | Alert pipeline instrumentation: state gauges pulled, run outcomes pushed | accepted |
| 0523 | 2026-08-16 | The metric point type is Measurement, not Sample | accepted |
| 0522 | 2026-08-16 | Metrics are samples on __system.metrics written by a collector worker; otel exposure moves to its own module | accepted |
| 0521 | 2026-08-15 | Only a declarer writes config, so the CLI creates nothing (amends 0518, 0520) | accepted |
| 0520 | 2026-08-15 | Cron jobs are declared like every other resource; built-in alert config moves into RegisterSystem (amends 0518) | accepted |
| 0519 | 2026-08-15 | Topic config lives in append-only declaration rows; topic keeps identity only | superseded |
| 0518 | 2026-08-15 | Config is code-owned, the latest declaration wins, and the CLI never writes config | accepted |
| 0517 | 2026-08-15 | Uniform config get/set/unset surface; alter dies in the CLI; Go Alter* verbs take tri-state Update[T] | superseded |
| 0516 | 2026-08-15 | AlertRepeatInterval moves to alert worker metadata; system config becomes a stub | accepted |
| 0515 | 2026-08-15 | Group tunables live in worker metadata as {default, override}; users tune through domain nouns | superseded |
| 0514 | 2026-08-15 | DestroySystem is RegisterSystem's inverse: drop every topic, then the control-plane schema | accepted |
| 0513 | 2026-08-14 | Create-ahead ships with the 95% backstop mark, and destroyed topics evict their claim entry | accepted |
| 0512 | 2026-08-14 | Producer create-ahead triggers at the partition's 80% mark id; heal path serialized by advisory lock | accepted |
| 0511 | 2026-08-13 | Binding sets are declared at consumer Register; replacement waits for zero live declarers | accepted |
| 0510 | 2026-08-01 | ConsumerType and its constants are demoted; NewConsumer defaults to cursor consumption | accepted |
| 0509 | 2026-08-01 | The retry surface is trimmed to Policy and the two error types | accepted |
| 0508 | 2026-08-01 | The concurrency package goes internal; consumers build queue and pool from ConsumerConfig | accepted |
| 0507 | 2026-08-01 | The public surface is organized by three audiences; plumbing types are demoted | superseded |
| 0506 | 2026-07-28 | Reconciliation refunds systemic failures on CLOSE, run by the probe winner; recovery is automatic | accepted |
| 0505 | 2026-07-28 | The breaker's trip threshold is a conservative debounce, not statistics | accepted |
| 0504 | 2026-07-28 | The breaker trips per instance; global OPEN is a quorum of locally-open instances | accepted |
| 0503 | 2026-07-28 | Breaker input is user error classification, recorded as error_class on the delivery row | accepted |
| 0502 | 2026-07-28 | The consumer gets an opt-in circuit breaker for systemic downstream failure | accepted |
| 0501 | 2026-08-01 | Schema provisioning is a library call, not an external migrate step | accepted |
| 0490 | 2026-08-13 | The register-time evaluator pass is log-only and never writes to the alerts topic | accepted |
| 0489 | 2026-08-13 | Checks declare themselves at `RegisterSystem`, with binds made idempotent by `UNIQUE` + `ON CONFLICT DO NOTHING` | accepted |
| 0488 | 2026-08-13 | "handler" and "publisher" are retired as domain nouns; the write door is `AlertController.Record` | accepted |
| 0487 | 2026-08-13 | The alert domain owns measurement and decision; producer and consumer inject it | accepted |
| 0486 | 2026-08-13 | Alert executors are worker definitions the manager claims, never embedded goroutines | accepted |
| 0485 | 2026-08-13 | There is no notifier component: notification is a side effect of `Record` observing a status change | accepted |
| 0484 | 2026-08-13 | Alert transitions are decided by one pure function, and evidence never enters it | accepted |
| 0483 | 2026-08-13 | The `__system.alerts` topic is the alert state store, dedup memory, and integration surface | accepted |
| 0482 | 2026-08-13 | One consumer group per check; the central alert dispatcher is dead | accepted |
| 0481 | 2026-08-13 | Each default alert check is its own cron job and worker-kind subpackage | accepted |
| 0473 | 2026-08-12 | Status and request-listing reads are flat per-fact queries composed in Go, not one CTE statement | accepted |
| 0472 | 2026-08-12 | "Firing" is retired from the codebase's vocabulary | accepted |
| 0471 | 2026-08-12 | `RunCronJob` takes a fresh v7 idempotency key per call and defaults to concurrency 'allow' | accepted |
| 0470 | 2026-08-12 | The scheduler produces each due job in its own transaction | accepted |
| 0469 | 2026-08-12 | Vendor the robfig cron schedule core instead of hand-rolling or adding a dependency | accepted |
| 0468 | 2026-08-12 | Registry verbs: idempotent `RegisterCronJob` that errors on config mismatch, `Alter` re-seeds `next_scheduled_time`, destroy gated by `AllowDestroy` | accepted |
| 0467 | 2026-08-12 | Status classification checks terminal outcomes before the not-head "superseded" case | accepted |
| 0466 | 2026-08-12 | `__system.job_requests` runs with `DeliveryLogModeAll` so successes leave rows | accepted |
| 0465 | 2026-08-12 | Job-request status is derived from existing tables, never written | accepted |
| 0464 | 2026-08-12 | Missed scheduled times are dropped: the scheduler walks to the newest due time and produces only that | accepted |
| 0463 | 2026-08-12 | Cron concurrency is enforced at consume time by the key lease, never by the scheduler | accepted |
| 0462 | 2026-08-12 | The job name is the routing key; there is no handler column | accepted |
| 0461 | 2026-08-12 | Scheduled work is built on the existing messaging machinery, with one compacted `__system.job_requests` topic | accepted |
| 0451 | 2026-08-04 | Consumption-loop package names keep the house stutter for now | accepted |
| 0450 | 2026-08-04 | rangeState and claimBuffer stay private, not their own packages | accepted |
| 0449 | 2026-08-04 | deliveryconsumer kept in the tree but not wired to run | accepted |
| 0448 | 2026-08-04 | No shared base package for the consumption-loop packages at first | superseded |
| 0447 | 2026-08-04 | uuid.UUID above the datastore, pgtype.UUID below; ErrLeaseLost declared where detected | accepted |
| 0446 | 2026-08-04 | ConsumerDatastore's phantom type parameter deleted | accepted |
| 0445 | 2026-08-04 | MessageMeta lives in the one new leaf, pkg/consumer/message | accepted |
| 0444 | 2026-08-04 | Consumption-loop packages sit under the door with their own narrow configs | accepted |
| 0443 | 2026-08-04 | pkg/consumer is a door, not a vocabulary layer | accepted |
| 0442 | 2026-08-02 | All input validation lives at the controller; datastores trust their inputs | accepted |
| 0441 | 2026-08-02 | Every domain gets the same three-layer package shape | accepted |
| 0431 | 2026-08-09 | The umbrella package is systemmanager, not Maintainer | accepted |
| 0430 | 2026-08-08 | NoInstanceTarget (-1) for self-claimed consumer loops | accepted |
| 0429 | 2026-08-08 | Duplicate beside pkg/maintain, don't retrofit it | accepted |
| 0428 | 2026-08-11 | EnsureNextPartition deleted without a replacement home | accepted |
| 0427 | 2026-08-08 | Snapshot verdicts are classify functions returning named enums | accepted |
| 0426 | 2026-08-08 | Producer split into pure factory plus Register; the stored lifecycleCtx dropped | accepted |
| 0425 | 2026-08-09 | One system manager row; the daemon is the same manager at deployment scope | accepted |
| 0424 | 2026-08-08 | The consumer inversion: consumption loops are worker rows the manager spawns | accepted |
| 0423 | 2026-08-08 | The manager respawns only on ErrInstanceLost and propagates every other error | accepted |
| 0422 | 2026-08-08 | Exclusivity is claim-per-instance, not claim-per-tick | accepted |
| 0421 | 2026-08-08 | One generic worker/worker_instance pair replaces per-feature maintenance/duty plumbing | accepted |
| 0411 | 2026-08-06 | FamilyHealth and VersionHealth live in pkg/admin, not as a pkg/metrics composition | superseded |
| 0410 | 2026-08-06 | Topic display identity stays two structured fields, not a concatenated name@vN string | accepted |
| 0409 | 2026-08-06 | There is no unversioned GetTopic(name); every topic read is version-addressed | superseded |
| 0408 | 2026-08-06 | The topic catalog column is named schema_version, accepting the overlap with schema_log.schema_version | superseded |
| 0407 | 2026-08-06 | The bridge derives its IdempotencyKey deterministically from the source message id | accepted |
| 0406 | 2026-08-06 | FamilyHealth never reports a compacted topic safe to retire | accepted |
| 0405 | 2026-08-06 | The topic catalog is keyed (name, schema_version), and constructors require SchemaVersion positionally | superseded |
| 0404 | 2026-08-06 | Message row metadata reaches consumer functions via consumer.MetaFromContext, not a signature change | accepted |
| 0403 | 2026-08-06 | Compaction's winner rule generalized to a signed caller-supplied rank compared before id | accepted |
| 0402 | 2026-08-06 | Migrating a compacted topic to a new version is a user-space bridge consumer, not a library verb | accepted |
| 0401 | 2026-08-06 | A message schema change is a new physical topic under the same name, never an in-place migration | superseded |
| 0400 | 2026-08-01 | Connection-death SQLSTATEs are retryable; resource-exhaustion, corruption, and misconfiguration codes are not | accepted |
| 0399 | 2026-08-01 | Process keeps per-tick-fatal claim errors; no loop-level retry/backoff | accepted |
| 0398 | 2026-08-01 | No DELETE CASCADEs and no triggers; integrity and logging stay in visible DML | accepted |
| 0397 | 2026-08-01 | No index on deliveries status for v1; reopen only on measured evidence, and prefer a partial index then | accepted |
| 0396 | 2026-08-01 | An idle poll short-circuits after the read-only snapshot statement | accepted |
| 0395 | 2026-08-01 | The pending (head, xmax) pair is stored unconditionally on every poll | accepted |
| 0394 | 2026-08-01 | Cursor claims stop at a proven head via a snapshot fence, not the visible MAX(id) | superseded |
| 0393 | 2026-08-01 | Binding changes are forward-only; history the FanOut mark has passed stays as routed | accepted |
| 0392 | 2026-08-01 | cursor claimed advances via GREATEST so a group running both paths cannot regress its frontier | accepted |
| 0391 | 2026-08-01 | FanOut's scan bound is a scalar subquery, not a join on old_values | accepted |
| 0390 | 2026-08-01 | FanOut delivers eagerly past the proven head; only the mark waits for proof | accepted |
| 0389 | 2026-08-01 | FanOut tracks a per-group high-water mark on the cursor table; LIFECYCLE groups register cursor rows and pin retention | accepted |
| 0388 | 2026-08-01 | The cursor-claim query locks the cursor row with FOR UPDATE in the old_values read | accepted |
| 0387 | 2026-08-01 | A missing cursor row errors loudly, detected by restructuring the claim query instead of adding an existence check | accepted |
| 0386 | 2026-08-01 | The abandoned-routine Add/Remove race is fixed structurally with a reaper goroutine | accepted |
| 0385 | 2026-08-01 | The abandoned-routines tracking map stays unbounded; no config knob | accepted |
| 0384 | 2026-08-01 | The partition drain loop is bounded, giving up via an unexported sentinel | accepted |
| 0383 | 2026-08-01 | Partition-drop batch size is a fixed constant of 100, not a config knob | accepted |
| 0382 | 2026-08-01 | Partition batches use plain DROP TABLE IF EXISTS with no DETACH first | accepted |
| 0381 | 2026-08-01 | topic.Destroy drops partitions in batches across multiple transactions | accepted |
| 0380 | 2026-07-28 | The datastore interfaces are deleted in favor of the concrete types | accepted |
| 0379 | 2026-07-28 | Multi-partition create-ahead (a PartitionsAhead knob) is rejected; PartitionSize is the lever | rejected |
| 0378 | 2026-07-28 | PartitionSafetyBuffer is deleted; the janitor always keeps the next partition created | accepted |
| 0377 | 2026-07-28 | Configs validate at construction via an exported WithDefaults-then-Validate pair | accepted |
| 0376 | 2026-07-28 | Always-on idempotency: make idempotency_key the enforced identity of message_log | superseded |
| 0375 | 2026-07-28 | Exception retry backoff reuses retry.Policy instead of a separate config surface | accepted |
| 0374 | 2026-07-28 | Datastore retry policy becomes retry.Policy, carried per config, not a global | accepted |
| 0373 | 2026-07-28 | QueueTimeout is renamed QueueMargin; WorkTimeout and AckMargin keep their names | accepted |
| 0372 | 2026-07-28 | Janitor and partition tuning fields are topic-scoped and persisted on the topic row | accepted |
| 0371 | 2026-07-28 | The table-name functions move to internal/topic | superseded |
| 0370 | 2026-07-28 | Topic administration moves to an admin object holding the datastore | accepted |
| 0369 | 2026-07-28 | The payload generic is named Message, cascading Work* type names to Message* | accepted |
| 0368 | 2026-07-28 | The consumer shutdown hook is deleted; the app that constructs the datastore closes it | accepted |
| 0367 | 2026-07-28 | Janitor splits into a gated public entrypoint and a private loop | accepted |
| 0366 | 2026-07-28 | Consumer session loops keep their ctx and run under a merged ctx; wind-down returns nil | accepted |
| 0365 | 2026-07-28 | Registration is once per instance, and lifecycle sentinels live in pkg/errors | accepted |
| 0364 | 2026-07-28 | A non-cancellable lifecycle ctx is an error, with an explicit DisableGracefulShutdown opt-out | accepted |
| 0363 | 2026-07-28 | Register validates the topic handle fail-fast: by-name fetch plus whole-struct compare | accepted |
| 0362 | 2026-07-28 | NewMessageProducer takes the raw PostgresDatastore and builds its datastores internally | accepted |
| 0361 | 2026-07-28 | MessageProducer.Register(ctx) captures the instance lifetime and gates Produce | superseded |
| 0356 | 2026-07-20 | No git tag marks this body of work | accepted |
| 0355 | 2026-07-20 | CLI flags map onto the sparse config structs via cmd.Flags().Changed | accepted |
| 0354 | 2026-07-20 | The CLI is a nested Go module, resolved locally through a gitignored go.work | accepted |
| 0353 | 2026-07-20 | delivery_log_<id> is always created; DisableDeliveryLog gates only the writes | accepted |
| 0352 | 2026-07-20 | Renaming a topic is its own verb, not a NewName field on the alter patch | accepted |
| 0351 | 2026-07-20 | renameTopic pins the id first and updates WHERE id = $1, never WHERE name = $1 | accepted |
| 0350 | 2026-07-20 | PartitionSize is immutable by omission from AlterConfig; dynamic partition bounds deferred | accepted |
| 0349 | 2026-07-20 | The alter UPDATE is one static COALESCE($n, col) statement, not a dynamically built SET list | accepted |
| 0348 | 2026-07-20 | AlterTopic takes a sparse pointer-per-field patch; nil means leave alone | superseded |
| 0347 | 2026-07-20 | Missing or mismatched schema surfaces as teaching errors, not raw Postgres errors | accepted |
| 0346 | 2026-07-20 | Migration registries are explicit ordered slices, not init() registration | accepted |
| 0345 | 2026-07-20 | One advisory lock id, two hold-times: session-scoped for a migrate run, xact-scoped for RegisterSystem | accepted |
| 0344 | 2026-07-20 | System scope and topic scope version independently | accepted |
| 0343 | 2026-07-20 | One append-only schema_log table; current version is the latest-by-id success row, not MAX(schema_version) | accepted |
| 0342 | 2026-07-20 | A migration is a sparse struct of func fields, run against a Querier that cannot manage transactions | accepted |
| 0341 | 2026-07-20 | Schema lives as versioned Go code; golang-migrate and its .sql files are deleted | accepted |
| 0328 | 2026-07-16 | The Datastore interfaces' fate was deferred to a standing cleanup phase, not decided mid-audit | accepted |
| 0327 | 2026-07-16 | Commit's per-exception writes are batched; RecordException stays one message at a time | accepted |
| 0326 | 2026-07-16 | Nested timeouts use context.WithTimeoutCause naming the budget that fired | accepted |
| 0325 | 2026-07-16 | deliveries went per-topic, and the six remaining shared tables were singularized, before the audit table shipped | accepted |
| 0324 | 2026-07-16 | delivery_log_<topic_id> records only failed attempts; a row's absence is the success signal | accepted |
| 0323 | 2026-07-16 | InTransaction does not retry | accepted |
| 0322 | 2026-07-16 | Partition self-heal in ProduceInTx is per-target via SAVEPOINT, with no opt-out | accepted |
| 0321 | 2026-07-16 | Multi-topic atomic publish exposes the transaction via a closure, not a declarative PublishAll | accepted |
| 0305 | 2026-07-14 | One queue-state query is the only derivation of the DB-truth health numbers | accepted |
| 0304 | 2026-07-14 | Logging goes through a caller-supplied interface with an io.Writer-backed default | accepted |
| 0303 | 2026-07-14 | The metrics snapshot is the single source for both the debug readout and the OTel instruments | accepted |
| 0302 | 2026-07-14 | pkg/ depends on the OTel metric API only, never the SDK or an exporter | accepted |
| 0301 | 2026-07-14 | The waterline rollup stays lazy; no cursor update at commit time | accepted |
| 0294 | 2026-07-12 | The retry.Wrap success-after-retries bug was fixed with a plain early-return, not a classification rewrite | accepted |
| 0293 | 2026-07-12 | The abandoned-goroutine registry is a mutex-guarded map keyed by (MessageId, Attempt), kept as plain in-process state | accepted |
| 0292 | 2026-07-12 | AbandonedRoutines.Remove runs after recover() within the same defer | accepted |
| 0291 | 2026-07-12 | Panic recovery's defer lives inside the spawned goroutine and sends into done | accepted |
| 0290 | 2026-07-12 | Timeout errors record the message id in last_error, never the work payload | accepted |
| 0289 | 2026-07-12 | WorkTimeoutGrace defaults to 100ms, sized from a measured scheduler latency | accepted |
| 0288 | 2026-07-12 | The hard per-message timeout is a detached-goroutine race, with abandonment accepted and tracked | accepted |
| 0287 | 2026-07-12 | One shared callSafely wraps consumerFunc for all three claim paths | accepted |
| 0286 | 2026-07-12 | Graceful shutdown narrows the interrupted lease instead of freeing it | accepted |
| 0285 | 2026-07-12 | Commit() classification lives inline at each call site; Wrap passes pre-classified errors through | accepted |
| 0284 | 2026-07-12 | The idempotency check's measured cost was cut with a batched CTE and a per-call opt-out | accepted |
| 0283 | 2026-07-12 | An idempotency_key claim table prevents double-publish on ambiguous commit acks | accepted |
| 0282 | 2026-07-12 | Datastore blips are retried via pkg/retry with explicit retryable/permanent classification | accepted |
| 0281 | 2026-07-12 | Every consumerFunc failure shape lands in the existing per-message retry/backoff/dead-letter path | accepted |
| 0273 | 2026-07-11 | The synchronous latest_key write cost was measured and accepted, hot-key serialization included | accepted |
| 0272 | 2026-07-11 | The compaction_key partial index was dropped once latest_key left it without a consumer | accepted |
| 0271 | 2026-07-11 | The correlated scan's cost was measured before committing to latest_key | accepted |
| 0270 | 2026-07-11 | A latest_key backfill was built, verified live, then reverted | rejected |
| 0269 | 2026-07-11 | Retention stays compaction-unaware; janitors garbage-collect dangling latest_key rows | accepted |
| 0268 | 2026-07-11 | latest_key is one shared table across all topics, not per-topic | accepted |
| 0267 | 2026-07-11 | The latest_key upsert guard compares id values, not commit order | accepted |
| 0266 | 2026-07-11 | Key deletion is expressed in the payload; there is no schema-level tombstone | accepted |
| 0265 | 2026-07-11 | Optional produce inputs travel in a ProduceOptions struct, not positional strings | accepted |
| 0264 | 2026-07-11 | The compaction_key index is partial, covering only keyed rows | superseded |
| 0263 | 2026-07-11 | The latest-per-key predicate is unbounded, not bounded by the claim's own high | accepted |
| 0262 | 2026-07-11 | latest_key trades a second synchronous write per keyed publish for an O(1) latest-per-key read | accepted |
| 0261 | 2026-07-11 | Compacted topics resolve latest-per-key at claim time, not by background deletion | accepted |
| 0248 | 2026-07-10 | Two routing_key slices sharing one topic share that topic's drop floor, by design | accepted |
| 0247 | 2026-07-10 | No deliveries.status index until real evidence demands one | accepted |
| 0246 | 2026-07-10 | deliveries stays one shared table across every topic, unlike message_log | accepted |
| 0245 | 2026-07-10 | Topics are registered explicitly and never auto-created on use | accepted |
| 0244 | 2026-07-10 | Topic identity is a per-call datastore parameter, not a field on the datastore | accepted |
| 0243 | 2026-07-10 | topic_id joins the keys of cursor/deliveries/binding; lease gets the column only | accepted |
| 0242 | 2026-07-10 | routing_key/bindings stay a coarser concept above topics, not folded into them | accepted |
| 0241 | 2026-07-10 | Each topic is its own physical table with its own sequence, partitions, and janitor | accepted |
| 0227 | 2026-07-08 | Partition automation is the Janitor loop in Go, not pg_partman | accepted |
| 0226 | 2026-07-08 | Retention shipped scoped to the one shared log, per-topic scoping deferred | superseded |
| 0225 | 2026-07-08 | Register creates cursor rows only for CURSOR-type groups | accepted |
| 0224 | 2026-07-08 | Partition labs swap message_log to a lab-scale width and restore the schema on exit | superseded |
| 0223 | 2026-07-08 | Retention respects a MIN(committed) drop floor unless explicitly opted out | accepted |
| 0222 | 2026-07-08 | Retention is a hybrid: whole-partition drop plus a bounded sweep of survivors | accepted |
| 0221 | 2026-07-08 | message_log is partitioned by RANGE (id), not created_at | accepted |
| 0208 | 2026-07-03 | FanOut keeps its full-table rescan; a per-group high-water mark is deferred | accepted |
| 0207 | 2026-07-03 | binding.kind, header_match, and their CHECK constraint were dropped | accepted |
| 0206 | 2026-07-03 | Matching is on routing_key only; no header or content matcher | accepted |
| 0205 | 2026-07-03 | Reads name their columns explicitly; SELECT * is out | accepted |
| 0204 | 2026-07-03 | BindTopic and ClearBindings are admin calls, not Datastore interface methods | accepted |
| 0203 | 2026-07-03 | Binding patterns are true wildcards, not NATS-style depth-precise matchers | accepted |
| 0202 | 2026-07-03 | Routing is one shared predicate evaluated at read time in both consume paths | accepted |
| 0201 | 2026-07-03 | Producers publish a routing_key attribute; groups opt in via binding rows; no binding means receive everything | accepted |
| 0192 | 2026-07-03 | ExceptionClaim payload unmarshal failure is fatal, not retried | accepted |
| 0191 | 2026-07-03 | A range past MaxRangeReclaims moves into the per-message exception path | accepted |
| 0190 | 2026-07-03 | Reclaim is one atomic UPDATE, not DELETE plus INSERT | accepted |
| 0189 | 2026-07-03 | String building in SQL uses concat(), not || | accepted |
| 0188 | 2026-07-03 | Resolution verbs are RecordExceptionSuccess/RecordExceptionFailure, not Ack/Nack | accepted |
| 0187 | 2026-07-03 | No ON CONFLICT on the exception INSERT | accepted |
| 0186 | 2026-07-03 | MessageException and MessageTerminal are two distinct types, not a flag | accepted |
| 0185 | 2026-07-03 | DrainExceptions runs as its own poll loop, separate from CursorClaim | accepted |
| 0184 | 2026-07-03 | ClaimExceptions dead-letters crash-looping rows before claiming | accepted |
| 0183 | 2026-07-03 | The waterline pins below unresolved exceptions; dead rows do not block it | accepted |
| 0182 | 2026-07-03 | Commit frees the lease before recording exception rows | accepted |
| 0181 | 2026-07-03 | A deliveries row exists only while a message needs individual attention; success is no row | accepted |
| 0166 | 2026-06-30 | Waterline advance moved to a lazy roller; per-message MoveCursor deleted | accepted |
| 0165 | 2026-06-30 | The cap on repeated reclaims was deferred until the exception path existed | accepted |
| 0164 | 2026-06-30 | Reclaim drains before fresh claim, one expired lease per poll | accepted |
| 0163 | 2026-06-30 | A lease covers (low, high], matching the claim read's convention | accepted |
| 0162 | 2026-06-30 | AdvanceWaterline is two statements, not one UPDATE | accepted |
| 0161 | 2026-06-30 | Crash recovery rides on a lease per claimed range, not per-message rows | accepted |
| 0145 | 2026-06-26 | `claimed` advances at claim time, before processing, with no lease | superseded |
| 0144 | 2026-06-26 | The claim reads the pre-update `claimed` via an `old_values` CTE, not PostgreSQL 18's `old` alias | accepted |
| 0143 | 2026-06-26 | `MoveCursor` gains the monotonic guard `WHERE committed < $1` | accepted |
| 0142 | 2026-06-26 | `committed` advances after each message, not once per batch at `high` | accepted |
| 0141 | 2026-06-26 | Two cursor frontiers (`claimed`, `committed`) carry the happy path with no per-message row | accepted |
| 0126 | 2026-06-23 | The poll loop waits one interval before its first claim | accepted |
| 0125 | 2026-06-23 | A `consumerFunc` error stops the whole poll loop; per-group retry and DLQ are deferred | accepted |
| 0124 | 2026-06-23 | Fan-out does not need a monotonic cursor guard; `MoveCursor` stays `SET position = $1` | superseded |
| 0123 | 2026-06-23 | The codebase keeps `message_log`/`cursor`/`position` naming rather than renaming to events/consumers | accepted |
| 0122 | 2026-06-23 | `Process` is a continuous poll loop, not a single-shot pass | accepted |
| 0121 | 2026-06-23 | A newly registered consumer group starts at position 0 and replays retained history | accepted |
| 0107 | 2026-06-23 | Claimed rows are drained with `CollectRows` before the claim transaction commits | accepted |
| 0106 | 2026-06-23 | Dropped lifecycle and lease machinery is parked as reference, not deleted | accepted |
| 0105 | 2026-06-23 | `FOR UPDATE` on the cursor serializes concurrent claims only, not the process-then-advance window | accepted |
| 0104 | 2026-06-23 | `MoveCursor` stays a bare `SET position = $1` with no monotonic guard | superseded |
| 0103 | 2026-06-23 | The cursor advances after each message, not once per batch | accepted |
| 0102 | 2026-06-23 | The cursor claim must `ORDER BY id`; an unordered claim silently loses messages | accepted |
| 0101 | 2026-06-23 | Consuming reads an append-only log through a per-group cursor instead of mutating message rows | accepted |
| 0086 | 2026-06-20 | The knob is set via ALTER DATABASE, and reset to on after the sweep | accepted |
| 0085 | 2026-06-20 | synchronous_commit=local is not measured | accepted |
| 0084 | 2026-06-20 | The on/off sweep is read by shape with best-of-3/max, and conc=1 is the number to trust | accepted |
| 0083 | 2026-06-20 | The crash lab proves off's cost is duplicate reruns, not loss, by SIGKILL with a widened WAL writer window | accepted |
| 0082 | 2026-06-20 | synchronous_commit=off is safe for this queue: it adds no new failure mode | accepted |
| 0081 | 2026-06-20 | Measure synchronous_commit only; skip the batch-ack measurement | accepted |
| 0067 | 2026-06-20 | Scaling levers are applied in a fixed order | accepted |
| 0066 | 2026-06-20 | MaxConns is set explicitly on the datastore pool | accepted |
| 0065 | 2026-06-20 | The claim index is a partial index on id covering ready and processing | accepted |
| 0064 | 2026-06-20 | Throughput is min(supply(batch), ack_capacity(workers)) | accepted |
| 0063 | 2026-06-20 | Claim per batch, record success or failure per message | accepted |
| 0062 | 2026-06-20 | The in-memory buffer stays shallow: depth is a lease-safety constraint, not a throughput lever | accepted |
| 0061 | 2026-06-20 | The prefetcher blocks on WaitForRoom; the buffer never drops a claimed row | accepted |
| 0047 | 2026-06-15 | Delivery is at-least-once; consumerFunc must be idempotent | accepted |
| 0046 | 2026-06-15 | The consumer owns the operational knobs; the datastore takes only connection params | accepted |
| 0045 | 2026-06-15 | The stuck window is the work timeout plus a 5s buffer | accepted |
| 0044 | 2026-06-15 | Lease reclamation is a claim-predicate branch, not a reaper daemon | accepted |
| 0043 | 2026-06-15 | The dead-letter queue is WHERE status='dead', not a separate table | accepted |
| 0042 | 2026-06-15 | Failures return to ready with a backoff on can_run_after; max attempts goes dead | accepted |
| 0041 | 2026-06-15 | The claim is row data (status + locked_at), not a held DB lock | accepted |
| 0023 | 2026-06-14 | ProducerFunc takes a concrete pgx.Tx | accepted |
| 0022 | 2026-06-14 | AppendMessage threads its transaction into a producer callback | accepted |
| 0021 | 2026-06-14 | The queue lives in the same Postgres database as the business data | accepted |
| 0006 | 2026-06-13 | The table is named message_log, not jobs | accepted |
| 0005 | 2026-06-13 | Graceful shutdown lets the in-flight batch finish under context.WithoutCancel | accepted |
| 0004 | 2026-06-13 | Batch limit pinned to 1 | accepted |
| 0003 | 2026-06-13 | The row lock is held for the entire processing duration | superseded |
| 0002 | 2026-06-13 | The message DELETE commits in the same transaction as the claim | accepted |
| 0001 | 2026-06-13 | Claims use SELECT ... FOR UPDATE SKIP LOCKED | accepted |