Skip to content

rfc: routing policies - #20

Open
alanshaw wants to merge 2 commits into
ash/rfc/dynamic-affinity-routingfrom
ash/rfc/routing-policies
Open

rfc: routing policies#20
alanshaw wants to merge 2 commits into
ash/rfc/dynamic-affinity-routingfrom
ash/rfc/routing-policies

Conversation

@alanshaw

@alanshaw alanshaw commented Aug 6, 2026

Copy link
Copy Markdown
Member

📖 Preview

Summary

Spaces are configured to use a routing policy which specifies the candidate nodes that can receive a blob. The policy can change over time but the reference to it does not.

It is an alternative affinity routing proposal that allows blobs uploaded to spaces to be routed to a particular storage node without having to specify said node in every invocation.

@alanshaw
alanshaw requested a review from a team August 6, 2026 09:54
Comment on lines +208 to +211
On bucket creation, after provisioning the bucket (space) with Sprue, Hilt
invokes `/routing/use` — signed with the tenant key, whose authority flows
from the bucket's root delegation — pointing the bucket at its region's
policy.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen if Hilt would invoke /routing/use before the space creation?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's impossible - the space/bucket DID must be the subject of the invocation.

@pyropy pyropy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me! I have posted a few questions most of them coming from my inexperience working with UCAN's.


**Routing policy** is an entity identified by a DID that owns a set of
storage-node DIDs — its _candidates_. It is a routing constraint for the
spaces that reference it, not a request that any particular node be selected,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a routing constraint for the spaces that reference it

Does this mean that there will be a routing policy property on the space? Would you mind explaining how can I find routing policy for a space?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, we could add a separate capability that returns the policy for a space or potentially augment our existing /space/info capability to return it.


The success value is an empty object.

### `/routing/get`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is related to my previous question -- how can one find routing policy DID for a space?

and MUST resolve the reference on every routing decision for a constrained
space.
- Changes require a `/routing/set` or `/routing/use` invocation before taking
effect, creating a window in which Sprue may route using outdated state.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there's a routing policy property on the space would it be possible to include it in the space creation request?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, do you you mean provisioning? I don't think it would be set before a space is provisioned.

The flow I have in mind is that when a regional provider is registered with Hilt you provide the service's DID. At this time Hilt creates a policy with a single node (/routing/set on Sprue) and records the policy DID. Note creating a policy DID == creating a public/private key. The policy DID will be stored in the DB with the provider information and used when Hilt creates a bucket for any tenant of that provider (/routing/use on Sprue).

@parkan

parkan commented Aug 7, 2026

Copy link
Copy Markdown

I think this probably the most solid proposal on the topic to date, more detailed review early next week

Comment on lines +245 to +249
Specified in [dynamic routing candidates](2026-07-dynamic-routing-candidates.md),
to which this RFC is a mutually exclusive alternative. It requires no Sprue
state and changes take effect immediately, but the constraint binds only
invocations that carry it: enforcement depends on every writer supplying the
correct candidates on every write.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a little concerned that by making this mutually exclusive with dynamic routing candidates we've drop the problem that RFC was written to solve: Ingot is co-located with a specific Piri, and per-invocation candidates existed to keep the write on the local node.

A region-wide policy only guarantees in-region placement — with N candidates, some writes accepted by a given Ingot instance could still hop to a sibling piri, in the hot path, increasing PUT latency, assuming there is ever more than a single node.

Could we compose these two options? e.g Keep candidates on /blob/add as a preference within the policy? Sprue could then select from the intersection of the invocation's candidates and the policy's, failing with CandidateUnavailable when the intersection is empty. The policy could remain the enforced outer bound for all writers, and picky writers could keep their locality hint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants