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.

Outbound egress

Calling Stripe, Slack or an SMTP host is ordinary work for a function. What a slice may dial is declared in the Driftfile.

Driftfile
atomic:
  egress:
    mode: allowlist              # open | allowlist, default open
    hosts:
      - api.stripe.com            # every port on this address
      - hooks.slack.com
      - smtp.sendgrid.net:587     # only this port
Mode What it declares
openAny public host on any port. The default, and what every slice does today.
allowlistReach only the declared hosts. A bare host admits every port on it; add :port to narrow it to that one.

The allowlist is enforced, not a hint.

drift file apply resolves every declared host to its current IPs and renders them into the slice's own outbound rule, so allowlist mode genuinely confines the slice's outbound traffic to what you named. A wildcard host (*.example.com) cannot become one of those rules, so it is refused rather than silently dropped: drift file lint rejects it offline, and the platform refuses it again if one somehow arrives. List concrete hostnames instead. A deploy reports what it did: egress allowlist applied (N hosts), or egress mode open when the block is absent or set back to open.

Private address space is blocked either way, and that block is real. RFC-1918 ranges, link-local (including the cloud metadata endpoint) and CGNAT are excepted from the slice's outbound network rule, so a function cannot reach the platform's internal services or anything on a private network whatever the Driftfile says.

The Go SDK's drift.HTTPRequest helper wraps a dial the allowlist refused in an EgressDeniedError carrying the host it was for, so a handler can reach for errors.As instead of parsing a message:

Go
var denied *drift.EgressDeniedError
if errors.As(err, &denied) {
    return 502, "Bad Gateway", map[string]string{"host": denied.Host}, nil
}

It is a best-effort signal rather than a certain one: the wrapping fires on the same underlying error a genuinely down host produces, so a host that is allowlisted but simply unreachable can be wrapped too. It also only covers calls made through that one SDK helper. A Go handler that opens its own http.Client sees the plain dial error instead, exactly as every other language's SDK always does.

Inspect and repair the list from the CLI:

Shell
drift atomic egress list                  # mode, declared hosts, resolved IPs
drift atomic egress test api.stripe.com   # local pattern match, no DNS lookup
drift atomic egress refresh               # re-resolve DNS and re-apply

There is deliberately no add or remove: the Driftfile is the source of truth, and drift file apply reconciles the list when that block changes.

Two edges the list still has.

Only IPv4 addresses become rules, so an IPv6-only host is not covered. And addresses are resolved when the list is applied rather than per request, which is what drift atomic egress refresh is for: reach for it when an allowlisted CDN's IPs have moved.