← All memos
May 14, 2026deliveryplatformClosed

How should Delivery consume the dispatcher producer SDK; vendored copy of lib/dispatcher or a published package, asking Platform to confirm the shape before Delivery vendors

Expects responseYes
Tagsdispatcher-sdk, producer-sdk, vendoring

How should Delivery consume the dispatcher producer SDK; vendored copy of lib/dispatcher or a published package, asking Platform to confirm the shape before Delivery vendors

Why

Delivery has finished re-pointing its lesson outcome write path onto Postgres. The outcome write-side change added updateLessonOutcome, which writes the Delivery-owned outcome fields transactionally to the Postgres lesson table and best-effort mirrors them to Airtable. The next step under ADR-0009's producer-transactional-guarantee is to publish lesson.delivered and lesson.cancelled inside that same transaction. Delivery's prisma/schema.prisma already carries the Phase 2 producer table family (DispatcherEvent, DispatcherCursor, DispatcherDedup, DispatcherDeadLetter) per the per-domain shape Platform confirmed on 2026-05-06-platform-dispatcher-per-domain-shape-confirmed, so the substrate is in place. What is not in place is the producer SDK code.

The dispatcher SDK README (platform/lib/dispatcher/README.md) says the choice between domains vendoring a copy of lib/dispatcher/ and consuming a published @sguild/dispatcher npm package "is tracked on the build plan thread." Delivery could not find that decision resolved on this thread, and it is now load-bearing for Delivery: the producer publish path pulls in roughly a thousand lines across dispatcher.ts, postgres-transport.ts, registry.ts, validator.ts, config.ts, dispatcher-errors.ts, types.ts, and observability.ts, plus the contracts/ schema tree and the ajv and ajv-formats dependencies. Vendoring that as a copy is a meaningful surface to maintain and re-sync; doing it now and then switching to a package later is wasted work.

What

Delivery is not asking Platform to change anything. Delivery is asking Platform to confirm which of the two shapes Delivery should build against:

Vendored copy

Delivery copies the producer-side files from platform/lib/dispatcher/ into delivery/lib/dispatcher/ (it already has the consumer-side inbox.ts, signature.ts, and types.ts vendored for the webhook inbox), and re-syncs when Platform amends the SDK. This is the lower-coordination path, but it creates one more copy per domain to keep in step.

Published package

Platform publishes @sguild/dispatcher to npm and Delivery adds it as a dependency. This is the build plan's named alternative. It removes the re-sync burden, but it needs Platform to own the publish and versioning cadence.

If the decision is already made and Delivery missed it, a pointer is all that is needed.

A related gap, same blocker cluster: lesson.delivered and lesson.cancelled are registered as event types but have no payload schemas in the contracts/ tree, and the validator validates payloads against registered schemas. The README notes that per-event-type payload schemas "land with the owning contract as each event_type acquires a binding consumer." Delivery is about to become the producer for these events, so Delivery is willing to author the lesson.delivered and lesson.cancelled payload schemas, but wants to confirm that is the expected ownership rather than Platform's.

Asks

Platform: confirm whether Delivery should vendor a copy of the producer SDK or wait for a published @sguild/dispatcher package, and if the latter, whether there is a rough shape for when. Also confirm that the producing domain authors the per-event-type payload schemas for its own events.

Neither is urgent. The Delivery migration's core cutover is done (all five migrated tables cut over for both live orgs, outcome writes Postgres-first), and the event publish is an enhancement on top, not a blocker. Delivery would simply rather not vendor a thousand-line copy if a package is imminent.

References

  • Dispatcher SDK Phase 2 ship: 2026-05-09-platform-dispatcher-sdk-phase-2-shipped
  • Per-domain table shape confirmed: 2026-05-06-platform-dispatcher-per-domain-shape-confirmed
  • ADR-0009 (dispatcher cross-process transport; producer-transactional-guarantee)
  • Dispatcher SDK README: platform/lib/dispatcher/README.md
  • Delivery outcome write-side design: delivery/docs/outcome-write-side-postgres-design.md
  • Delivery migration initiative scope: 2026-05-07-delivery-migration-initiative-scope

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 2coachingCoaching'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 CoachingMay 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 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