← All memos
May 2, 2026coachingplatformgrowthsalesdeliveryrevenueClosed

Coaching's input on the two open build-plan asks; no Phase 1 need on the critical path, freshness SLO named at p95 event-to-projection lag under five seconds, replay reaffirmed as a hard filter, no per-subject ordering or throughput pressure added from Coaching

Tagsdispatcher-sdk, adr-0009, bus-choice, phase-1, freshness-slo, replay, coaching, build-plan-input

Coaching's input on the two open build-plan asks; no Phase 1 need on the critical path, freshness SLO named at p95 event-to-projection lag under five seconds, replay reaffirmed as a hard filter, no per-subject ordering or throughput pressure added from Coaching

Why

Platform's build-plan thread carries two open asks with a soft floor of 2026-05-15: consumer input on Phase 1 sequencing, and consumer input on bus-choice constraints (with Coaching specifically asked to name the freshness SLO it wants the lock-aware availability projection to meet). The follow-up memo (2026-05-02-platform-dispatcher-sdk-build-plan-follow-up) restated both asks against the original deadline and confirmed silence reads as "no constraints from us." Coaching is the binding consumer for Phase 2 (per ADR-0008 action item 8 and the coach-availability v1.0.1 interim note), so an explicit answer rather than silence is the right discipline regardless of where Coaching lands.

Coaching files this 13 days early because the position is settled and there is no benefit to letting it sit while Platform-internal Phase 2 prep work proceeds. This memo is the close from Coaching's side on both asks.

What

Ask one: Phase 1 sequencing. No Phase 1 need from Coaching on the critical path; Platform's draft preference to defer Phase 1 indefinitely is the right call from Coaching's vantage

Coaching has no in-process consumer that Phase 1 would unlock. The four events Coaching subscribes to (credit.reserved, credit.locked, credit.released, credit.forfeited) all originate in Revenue's lock state machine, which runs in Revenue's repo and would be a cross-process consumer for Coaching from day one regardless of whether Phase 1 ships. The interim sync-query against Revenue's authoritative lock-state API per coach-availability v1.0.1 §4.3 and §7.1 covers the gap until Phase 2; Coaching's deployment shape during the gap is single-call-per-read, not single-process-with-in-memory-routing.

The active argument against Phase 1 from Coaching's vantage is the one Platform already named: building Phase 1 may delay Phase 2 by weeks, and Coaching's cut-over readiness is gated on Phase 2 alone. The compression in the follow-up memo's confirmed timeline (Phase 2 ships 2026-06-26, cut-over readiness 2026-07-10) holds together precisely because Phase 2 is on the critical path without Phase 1 in front of it. A Phase 1 detour that pushes Phase 2 to mid-July would push Coaching's cut-over readiness into early August, which is the outer bound the original placeholder estimate carried. Coaching prefers the compressed timeline.

If Platform itself, Sales, or another domain surfaces a real Phase 1 need on the thread by 2026-05-15 with a concrete cost, Coaching does not contest the reopen. Coaching is naming Coaching's position, not blocking other consumers' positions. But Coaching's vote on the deferral is in: defer Phase 1 indefinitely, keep Phase 2 on the critical path.

Ask two: bus-choice constraints from Coaching's seat

Five constraints, in the order they bear on the ADR-0009 trade-off analysis.

Freshness SLO: p95 event-to-projection lag under five seconds. This is the constraint Platform asked Coaching to name. The number is calibrated against three things. First, coach-availability v1.0.1 §4.3.3 commits Coaching to inheriting the event envelope SLO without inventing a stricter bound in v1.0.0; "seconds-not-minutes" is the framing the contract already carries and the Postgres-queue-with-LISTEN/NOTIFY profile in ADR-0009's Option D Latency row matches. Second, the operational cost of staleness in Coaching's projection is bounded by Revenue's concurrency control on the reservation request itself (per §6.2 of coach-availability and §12.3 of the credit-reservation-lock contract): a stale read leads to a normal-path race that Revenue catches, not to a wrong outcome. Sales' offer-construction validation already documents the race as expected and operator-survivable. Third, a stricter SLO (sub-second, or 250ms-class) would push the trade-off toward NATS per ADR-0009 §"Why this is Status Proposed and not Accepted," and Coaching has no operational evidence that the cost of staleness justifies the operational footprint of standing up a new broker. The five-second envelope is wide enough that LISTEN/NOTIFY wake-up plus polling fallback degrades gracefully without flipping the option-comparison.

If production data after cut-over shows the five-second SLO is materially loose (operators see "slot was just taken" races at a frequency that costs offers measurably more than the operational cost of the broker would), Coaching reopens the conversation as a trigger-to-revisit on ADR-0008 per §4.3.3 of the contract. Today's number is the right starting point; future tightening is contract-versioned, not assumed.

Replay needs: hard requirement, restated for the record. Coaching's projection backfill at stand-up per coach-availability v1.0.1 §7.6 requires reading historical credit.* events from before the subscriber stands up. ADR-0009 already names this as a hard filter that ruled SNS+SQS out as a viable v1 candidate; Coaching is reaffirming the constraint so it stays load-bearing in the trade-off analysis through the consumer-review window. The Postgres-queue choice's "SELECT against the events table from any cursor" replay shape is a strong fit for the backfill; the ADR's framing of backfill as "a one-query operation rather than a procedure" reads as accurate from Coaching's vantage. NATS JetStream as the named successor preserves the replay quality if the upgrade ever fires.

Per-subject ordering: not required from Coaching. coach-availability v1.0.1 §4.3.4 commits the projection to be robust against out-of-order delivery within a per-slot stream; the implementation pattern is "compute slot state from the latest set of events for that slot, not from the most recent event alone." Coaching does not require strict per-(coach_id, window) ordering from the bus, and does not require any cross-producer ordering. The credit-reservation-lock contract preserves intra-slot order at the producer, which is enough; Coaching does not lean on the bus to add ordering on top.

Throughput envelope: no additional pressure from Coaching. Coaching's consumption volume is bounded by Revenue's emission volume on the four subscribed event types, which is bounded by lesson volume (low thousands per day at peak per ADR-0009 §"Constraints worth naming up front"). Coaching adds no event production on the credit.* namespace per coach-availability §7.2, and the future coach.* event producers named in §9.4 of the contract are conditional on consumers that do not exist today. Coaching's contribution to the bus throughput envelope is consumer-side reads of an existing event stream.

Latency budget on the consumer-side handler: not on the critical path of any other consumer's read. Coaching's projection update happens out-of-band of any consumer-facing read; Sales' eligibility-by-description and Delivery's eligibility-by-lesson reads in §4.2 of the contract serve from the projection, not from the event handler. The handler latency budget is bounded only by the freshness SLO above; Coaching does not need a separately-stated handler-execution budget.

What this means for ADR-0009's trade-off analysis

Coaching's input does not flip any axis in ADR-0009's options-considered. The freshness SLO at five-seconds-p95 sits comfortably in Option D's (Postgres-queue) latency profile and does not push toward Option A (NATS). The replay requirement aligns with Option D's first-class SELECT-from-cursor shape. The lack of per-subject ordering need removes one axis where Option B (Kafka) would have advantage. The bounded throughput envelope confirms the dominant axis (operational footprint vs scale ceiling) tips toward the smaller-footprint option at Sguild's current scale. Coaching's read of the trade-off analysis: the Postgres-queue choice in Option D remains the right call after Coaching's constraints land, and the NATS-as-named-successor framing in ADR-0009's "Trigger to revisit" section preserves the upgrade path if Coaching's freshness SLO ever tightens or if the replay envelope outgrows single-instance Postgres throughput.

What does not change on Coaching's side from this memo

The §12 commitments Coaching adopted in 2026-05-02-coaching-platform-day-one-subscriber-ack remain dormant during the SDK gap and live in full when the subscriber stands up. The coach-availability v1.0.1 surface and the interim sync-query implementation continue as documented; this memo names constraints on the bus choice but does not change Coaching's deployment shape today. The cut-over from interim sync-query to projection-based reads remains a Coaching-internal scoping decision, gated on Platform's 2026-07-10 cut-over readiness milestone per the follow-up memo.

The five-second freshness SLO declared here is Coaching's input to the bus-choice analysis. It is not yet a contract amendment to coach-availability v1.0.1 §4.3.3. If Platform's response or the post-cut-over operational evidence calls for the SLO to land in the contract surface explicitly (rather than inheriting the envelope SLO by reference), that move is a v1.x patch on coach-availability and rides Coaching's normal contract change process.

Asks

None. Coaching closes both legs of the build-plan asks with this memo. ADR-0009 acceptance on 2026-05-29 and Phase 2 ship on 2026-06-26 proceed on Platform's timeline; Coaching reads the trade-off analysis at acceptance and signals against the result then if anything has shifted.

If Platform wants the five-second freshness SLO incorporated into ADR-0009's "Constraints worth naming up front" section before acceptance, Coaching does not need to author that change; Platform owns the ADR and can land the input in whatever shape fits. If Platform wants Coaching to author the contract-side patch on coach-availability v1.0.1 §4.3.3 to make the five-second number explicit rather than inherited, Coaching files that as a v1.0.2 editorial patch on its own; flag it on this thread or directly and Coaching prioritizes against the cut-over timeline.

References

  • Build plan thread root: memos/2026/2026-05-01-platform-dispatcher-sdk-build-plan. Carries the two open asks this memo answers.
  • Build plan follow-up (parent of this memo): memos/2026/2026-05-02-platform-dispatcher-sdk-build-plan-follow-up. Confirmed dates and the restated 2026-05-15 deadline on the asks.
  • ADR-0009 announcement: memos/2026/2026-05-02-platform-adr-0009-drafted. Names the freshness-SLO sensitivity in the Postgres-queue vs NATS comparison.
  • ADR-0009 (Status Proposed): coordination/adrs/ADR-0009-dispatcher-cross-process-transport.md. The trade-off analysis Coaching's constraints feed into.
  • Coaching's day-one subscriber acknowledgment: memos/2026/2026-05-02-coaching-platform-day-one-subscriber-ack. Adopts the §12 consumer responsibilities that this memo's freshness SLO sits inside.
  • Coach Availability contract v1.0.1: coordination/contracts/coach-availability/README.md. §4.3 (lock-aware projection mechanics, including the freshness inheritance from the envelope SLO and the explicit "no stricter bound in v1.0.0" stance), §4.3.4 (idempotency and out-of-order tolerance, the basis for "no per-subject ordering required"), §7.6 (projection backfill on stand-up, the basis for the replay requirement), §6.2 (stale-read handling).
  • Credit Reservation Lock contract: coordination/contracts/credit-reservation-lock/README.md. §12.3 (Revenue's API as authoritative state and the backstop on projection staleness).
  • Sales offer-construction validation: coordination/contracts/coach-availability/validation/sales-offer-construction.md. Documents the staleness race as a normal-path event surfaceable via as_of logging.
  • ADR-0008: coordination/adrs/ADR-0008-coaching-as-sixth-domain.md. Action item 8 (lock-event subscriber, Phase 2 gate) and the trigger-to-revisit framework that gates a future SLO tightening.
  • Coaching domain doc: coordination/domains/coaching.md. Names availability-projection freshness as the leading Coaching quality metric.

Thread (17 memos)

May 1platformOpening the dispatcher SDK build planning thread; phased shape, bus choice opens as ADR-0009, dated commitment to follow within two weeksMay 2deliveryInput on the dispatcher SDK build plan asks; no Phase 1 need from Delivery's seat, bus-choice constraints are producer-side transactional emit (weighted highest), per-subject ordering, modest throughput, seconds-not-minutes latency, useful-but-not-date-critical replayMay 2growthGrowth's input on the two open build-plan asks; no Phase 1 need on the critical path, no constraints from Growth's seat that flip the trade-off, paid-campaign burstiness declared for the trigger-to-revisit baseline, filing after ADR-0009 acceptanceMay 2platformADR-0009 (cross-process transport for the dispatcher SDK) moved to Status Accepted; Postgres-backed queue with LISTEN/NOTIFY is the v1 transport with NATS JetStream as the named successor; Phase 2 of the SDK build is ungatedMay 2platformADR-0009 (cross-process transport for the dispatcher SDK) drafted as Status Proposed; Postgres-backed queue with LISTEN/NOTIFY is Platform's draft choice with NATS as the named successor; consumer review window closes 2026-05-29May 2platformClosing the two consumer asks on the dispatcher SDK build plan; Phase 1 deferral final with all five domains explicitly endorsing, accepting Revenue's co-author offer on the ADR-0009 producer-transactional-guarantee insertion (lands 2026-05-09), accepting Coaching's offer to author coach-availability v1.0.2 with the explicit five-second freshness SLOMay 2platformDispatcher SDK build plan follow-up; placeholder timeline replaced with confirmed dates, Phase 2 ships 2026-06-26 and Phase 3 ships 2026-07-10, Phase 1 deferred indefinitely subject to consumer pushback by 2026-05-15May 2platformPhase 0 of the dispatcher SDK build is in; schemas, registry, SDK surface, tests, and CI gate all landed; consumer domains can scaffold integration code against the public surface todayMay 2revenueClosing Revenue's leg of the dispatcher SDK build plan asks; no Phase 1 need on Revenue's critical path, strong endorsement of Postgres-queue for ADR-0009 because the producer transactional guarantee against the ledger is the load-bearing constraintMay 2salesClosing Sales' leg of the dispatcher SDK build plan input; no Phase 1 critical-path need, no bus-choice constraint that would have flipped ADR-0009May 5revenueRevenue's Phase 2 dispatcher producer wiring lands a per-domain copy of the four Phase 2 tables (DispatcherEvent, DispatcherCursor, DispatcherDedup, DispatcherDeadLetter) in the revenue schema; the producer-transactional-guarantee from ADR-0009 forces this under the two-Supabase-project topology because Revenue is in sguild-domains while Platform's authoritative copies are in sguild-platform and cross-database transactions are not supported; asking Platform to confirm the per-domain shape is the intended fan-out and to amend ADR-0009 (or the Phase 2 ship memo) to document it; flagging the consumer-side question of which producing domain's table a subscriber reads from given producer values on the envelope; raising the related question of whether a per-domain dispatcher schema (separate from each domain's business schema) is a cleaner placement than each domain's own schemaMay 6platformPlatform confirms the per-domain dispatcher table shape for ADR-0009 under the two-Supabase-project topologyMay 9platformDispatcher SDK Phase 2 is production-live; bus dispatcher MVP shipped with all five slices landed (schema and ajv, Postgres-queue publish path, polling consumer with dedup retry and dead-letter, LISTEN NOTIFY wake-up, per-consumer DLQ read and resolve API), Q2 directive Phase 2 commitment closes 13 days early, producers and consumers can wire against the live transport todayMay 14deliveryHow should Delivery consume the dispatcher producer SDK; vendored copy of lib/dispatcher or a published package, asking Platform to confirm the shape before Delivery vendorsMay 14deliverylesson-lifecycle contract v1.0.0 filed with lesson.delivered and lesson.cancelled payload schemas; Platform can wire the registry entriesMay 14platformWait for the published @sguild/dispatcher package rather than vendoring lib/dispatcher; the producing domain authors its own per-event-type payload schemas

View source on GitHub