drift Docs
Start
What is Drift?
The tour, if you are new here.
Use cases
Whether Drift does your thing.
Getting started
Nothing to deployed, in one command.
Architecture
How a slice is put together.
What it costs
The free grant, four unit prices, two rules.
Build
Canvas
Static sites, same origin as your API.
Tools
Operate
Auth
Route gates, API keys and your account.
Security
Boundaries, sandboxing and hardening.
Troubleshooting
Error codes
What went wrong, and what to do about it.
Legal
Acceptable use
What a slice may not be used for.
Data processing
The DPA, and every sub-processor.

Edge Links

A link lets one slice call another slice you own: an app calling your billing slice, a set of services calling your own observability slice. The call stays inside Drift. It never crosses the public internet, it never passes the public router, and the function making it never learns where the other slice lives.

A link is directed. Linking site to billing lets site call billing, and nothing more: billing cannot call back unless it links site too.

Declaring it

Driftfile
edge {
  links = ["billing", "observability"]
}

Each name is another slice in your account. When the key is present it is the whole list: the apply adds every link the slice does not have and removes every live link the list does not name, adding first so a link you keep is never down between the two. It prints a line for each change:

  ✓ linked → billing
  ✓ unlinked → admin (not in edge.links)

links = [] removes them all, and leaving the attribute out leaves the links as they are. drift plan lists what would be added (+ link billing added), removed (- link admin removed, which drift apply asks you to agree to) and kept (link observability unchanged). A slice cannot link to itself, and drift apply refuses the file before anything is sent if it tries: edge.links names "site", the slice this file is applied to; a slice cannot link to itself.

A name that is not a slice of yours is refused by the platform with no slice named 'billing' in your account (links are same-user only). Adding or removing a link re-renders both slices, and the calling slice restarts to pick up the change.

From the CLI

Command What it does
drift slice link add <slice>Let the active slice call <slice>
drift slice link listThe slices the active slice is linked to, with each one's public hostname
drift slice link remove <slice>Remove a link
Go
$ drift slice link add billing
Linked → billing
  Call it from your functions:
    drift.Edge.Slice("billing").Post("/api/...", body)
  (an in-cluster path through the slice runtime; billing authenticates the call like any other)

The /api/... in that output is the CLI's own placeholder for your route. A link made with a command is removed by the next apply of a file whose links attribute does not name it.

From a function

Edge.Slice(name) is the client, in every SDK:

Go
resp, err := drift.Edge.Slice("billing").Post("/api/charge", body)

Get(path), Post(path, body) (which JSON-encodes the body) and Request(method, path, headers, body) are the calls. Utilities spells the client in each of the six languages, and the older drift.Slice(name) spelling it still answers to.

A call to a slice this one is not linked to fails before any connection is made, with an error that names the fix:

drift: slice "billing" is not linked: declare it under edge.links in the Driftfile (or run drift slice link add billing)

How the call travels

  1. The function is handed a local address. For each link the slice's environment carries DRIFT_LINK_<NAME>_URL, set to http://127.0.0.1:8001/link/<name>: the slice's own Atomic listener, on loopback. The SDK builds the URL from it; a missing variable is the "not linked" error above.
  2. The runtime relays the call. The relay looks the name up among the slice's links, and only the runtime holds the real addresses. A name it does not hold is refused there, with a 404 carrying the same sentence the SDK uses, before any connection is opened. Only a caller on the slice's own loopback can use the relay; to anyone else the path does not exist.
  3. The target answers inside the cluster. The relay carries the method, the path after /link/<name>, the query, the headers and the body to the target's own listener, and streams the answer back byte for byte, so a Server-Sent Events or WebSocket reply works through it. Of all the slices on the platform, the target's network rule admits only the ones that link to it.

Because the function only ever dials loopback, the runtime's refusal of private addresses (see Egress) stays in force: a function cannot reach the other slice, or any other, around the relay. A link is not an egress host either, so it needs no entry in the egress block's hosts and widens nothing toward the public internet.

A linked call never passes the public router. The target's allowlist, rate limit and site gate are the router's rules, so they are not applied to it. What the target's Pulses check themselves, such as an auth block with an api_key, still applies.

Who is calling

A linked call may carry an X-Drift-Slice header, and CallerSlice(req) reads it on the far end. It authorises nothing. It is a header, and whoever makes a call writes its headers: with two links, either caller can present itself as the other. Use it for logging and routing, and when a slice needs to know which caller it is talking to, give each one its own credential, such as an API key the callee checks.

The SDKs send it only when the runtime supplies the calling slice's name, and a caller's own header by that name never replaces it. In a deployed function the runtime does not supply one, so the header is normally absent rather than empty.

What a refusal looks like

Where What you see
The SDK, for a name with no linkdrift: slice "billing" is not linked: declare it under edge.links in the Driftfile (or run drift slice link add billing), before any network I/O
The relay, for a name with no link404, with the same sentence
The relay, for a linked slice it cannot reach502, with the error linked slice "billing" could not be reached. It names the link and never the address behind it.
drift slice link add, for a slice that is not yoursno slice named 'billing' in your account (links are same-user only)

Limits

Limit Value
Who can be linkedSlices in the same account. A slice you received from another account cannot link to the slices you created.
Connecting to the target5 seconds
A relayed connection with nothing movingClosed after 300 seconds, the longest function timeout a slice can buy
TransfersA slice with a link in either direction cannot be transferred until the link is removed

A linked slice can also serve one of this slice's hostnames: see Fronting a linked slice.