Step 6 of RFC 1449. Demand-gated — do not build speculatively. Blocked by step 5.
Why this is last, not first
The port boundary was never the constraint; the pull model was. Once claim reads only its own tables, Store divides cleanly:
EventStore — commit, query, query_stats, scan/restore, forget_pii, notify
SubscriptionStore — subscribe, claim, ack, block, unblock, defer, prioritize, reset, query_streams
correlate is the only component holding both, and it is a pipeline, not a distributed transaction: read from the event store at a checkpoint, write to the subscription store idempotently. streams.at and correlated remain event-store ids, but the subscription store only ever compares them — the opaque-monotonic-token property Kafka offsets and Axon tracking tokens have.
What it costs
A second port, a second TCK, a second capability matrix, and an untested adapter × adapter combinatorial surface. It buys a deployment option and no performance that step 5 has not already delivered.
truncate remains the one genuinely cross-store operation and needs a resumable two-phase protocol — tractable, since close is low-cadence and #1389 already made an interrupted close resumable.
The gate
Open this only for a workload where the events half is the constraint in a way the subscription half is not — archival events on object storage with leases in Postgres is the shape that would qualify. Re-run store-split-claim.bench.mjs against the mark (not the old joined baseline) so the decision is made on current numbers.
Absent that workload, the correct outcome for this ticket is closed as not needed, which is a successful result for the milestone rather than a failure.
Step 6 of RFC 1449. Demand-gated — do not build speculatively. Blocked by step 5.
Why this is last, not first
The port boundary was never the constraint; the pull model was. Once
claimreads only its own tables,Storedivides cleanly:EventStore—commit,query,query_stats,scan/restore,forget_pii,notifySubscriptionStore—subscribe,claim,ack,block,unblock,defer,prioritize,reset,query_streamscorrelateis the only component holding both, and it is a pipeline, not a distributed transaction: read from the event store at a checkpoint, write to the subscription store idempotently.streams.atandcorrelatedremain event-store ids, but the subscription store only ever compares them — the opaque-monotonic-token property Kafka offsets and Axon tracking tokens have.What it costs
A second port, a second TCK, a second capability matrix, and an untested adapter × adapter combinatorial surface. It buys a deployment option and no performance that step 5 has not already delivered.
truncateremains the one genuinely cross-store operation and needs a resumable two-phase protocol — tractable, since close is low-cadence and #1389 already made an interrupted close resumable.The gate
Open this only for a workload where the events half is the constraint in a way the subscription half is not — archival events on object storage with leases in Postgres is the shape that would qualify. Re-run
store-split-claim.bench.mjsagainst the mark (not the old joined baseline) so the decision is made on current numbers.Absent that workload, the correct outcome for this ticket is closed as not needed, which is a successful result for the milestone rather than a failure.