drift Docs
Start
What is Drift?
The tour, if you are new here.
Why Drift?
The case for a smaller cloud.
Getting started
Nothing to deployed, in one command.
Architecture
How a slice is put together.
What it costs
The free grant, five unit prices, two rules.
Build
Canvas
Static sites, same origin as your API.
Tools
Operate
Auth
Accounts, tokens and scopes.
Security
Boundaries, sandboxing and hardening.

Atomic 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.

The allowlist is declared, not enforced.

A Driftfile's hosts list is validated and recorded, and drift project deploy says so in as many words: it reports the allowlist as declared for N hosts, and not yet enforced by the platform. Every slice reaches the public internet as if the mode were open. Read the block as a statement of intended reach, and keep the authentication and secret hygiene you would have used without it. The private-range block below is a separate mechanism and it is live.
Driftfile
atomic:
  egress:
    mode: allowlist              # open | allowlist, default open
    hosts:
      - api.stripe.com
      - hooks.slack.com
      - smtp.sendgrid.net:587     # port defaults to 443
Mode What it declares
openAny public host on any port. The default, and what every slice does today.
allowlistThe intent to reach only the declared hosts, on the declared port (443 when omitted).

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 carries an EgressDeniedError that wraps a refused dial with the host it was for, so a handler can tell “my allowlist is wrong” from “the remote is down” once the allowlist does gate traffic. It is Go's alone; the other five SDKs return the underlying dial error unwrapped.

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

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 project deploy reconciles the list when that block changes.

Three edges the list already has.

A *.example.com wildcard passes schema validation and egress test reports it as a match, but the resolver skips it, so list concrete hosts. 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.