Skip to content

Support for stream forking (Stream-Forked-From / Stream-Fork-Offset) per the Durable Streams protocol #16

Description

@dkachur1

The base Durable Streams protocol defines stream forking via PUT with Stream-Forked-From and Stream-Fork-Offset headers (copy-on-write, refcounted soft-delete on the source when forks are still active). This server doesn't implement it, and it isn't listed as a known gap anywhere I could find � not in FEATURES.md, and the vendored docs/durable-streams-spec.md doesn't include the fork section at all (its own §4.2 is "List streams").

Use case: we run per-conversation durable streams for a chat agent (StreamDB/state-protocol on top of prisma/streams). When a user edits an earlier message or regenerates a reply, the natural model is a branch: fork the conversation stream at the edited turn's offset, keep the original branch addressable, and let the new branch diverge. Without server-side fork support, we're limited to destructive supersede (delete-and-rewrite rows in place), which loses the ability to keep multiple branches alive or let a user switch back to an earlier one.

Proposed behavior (matching the protocol spec):

  • PUT /v1/stream/{name} with Stream-Forked-From: and Stream-Fork-Offset: creates a new stream that inherits all data from the source up to that offset.
  • Source and fork may implement inheritance via copy-on-write or pointer-stitching â�� implementation detail, not prescribed by the protocol.
  • Deleting a stream with active forks soft-deletes it (410 Gone to direct access) while forks can still read the inherited range; GC once the last referencing fork is deleted.

Alternatives considered: row-level supersede (what we do today) � works, but is destructive and can't represent multiple live branches of the same conversation, which is the actual UX we're after.

Happy to help test against a real implementation, or contribute if there's appetite for a PR � wanted to check whether this is a deliberate scope exclusion before writing one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions