Skip to main content

Production-Grade Edge Config, Per App: Redirects, Headers, CORS, WAF, and More

· 5 min read
FoundryDB Team
Engineering @ FoundryDB

When the edge gateway launched, you could put a custom domain in front of your app, get an automatic certificate, cache responses, rate limit per IP, and run a detect-only WAF. That covered the headline cases. But production has a longer list: a permanent redirect for a moved path, an HSTS header you can finally turn on, a CORS policy for the front end on another domain, an IP allow list for a staging environment, a maintenance page during a deploy. Each of those used to mean code in your origin or config you maintained yourself.

Now the full edge configuration surface is exposed per app, in the Domains & Edge tab and across the API. Redirects, headers, CORS, access control, compression, limits, and a WAF that can now block, all configured per app and applied across every EU point of presence without touching your container or redeploying anything.

PoP failover & autoscaling
Nearest PoP serves each client · HA pair + autoscaling
Clientnearest PoPserving address →PoP pairactive + standby⇢ forwardApp originyour app
Active · serving addressHot standbyFailed nodeAdded capacityClient requestForward to origin (dashed)

What you can configure now

The settings are grouped the way the console groups them.

Routing. Redirects map an incoming path to a destination URL with a 301, 302, 307, or 308 status. The redirect happens at the edge, so a redirected request never reaches your origin.

Headers. Set or remove headers toward your origin and toward the client. Turn on HSTS with a max-age, include_subdomains, and preload. Inject a unique request id on every request and echo it back, so one request correlates across edge analytics and your origin logs.

CORS. Allowed origins (a wildcard or a concrete list), methods, request headers, exposed response headers, credentials, and a preflight max-age. The platform enforces the rules browsers themselves enforce: a wildcard origin cannot be combined with credentials, and a wildcard cannot be mixed with a concrete list.

Access control. An IP allow list (default-deny once it is non-empty), an IP deny list, an allowed-methods list, blocked path prefixes, HTTP Basic Auth, and a maintenance mode that serves a fixed status and body to everyone except a bypass list.

Performance. Gzip response compression, and the per-path cache rules that shipped at launch.

Limits. A maximum request body size, and the per-PoP token-bucket rate limiter. When a point of presence grows past a single node, the limiter can be backed by a Valkey store so the nodes in that PoP share one counter.

Security. The WAF now has three modes: off, detect, and block. Detect logs and counts matches while still forwarding the request. Block rejects matches at the edge.

Turning it on

Edge settings are a single call. Here a moved path gets a permanent redirect, a CORS policy is set for a front end on another domain, a staging-style basic-auth gate is enabled, HSTS is switched on, and the WAF moves to blocking:

curl -X PUT https://api.foundrydb.com/app-services/$APP_ID/edge/settings \
-H "Authorization: Bearer $FOUNDRYDB_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"redirects": [
{ "from_path": "/old-pricing", "to_url": "https://example.com/pricing", "status": 301 }
],
"cors": {
"allowed_origins": ["https://app.example.com"],
"allowed_methods": ["GET", "POST"],
"allow_credentials": true,
"max_age": 600
},
"hsts": { "max_age": 31536000, "include_subdomains": true, "preload": true },
"basic_auth": { "users": [{ "username": "team", "password": "set-once" }] },
"waf": { "mode": "block" }
}'

A save bumps a configuration version, and the fleet converges on it across all points of presence within a short window. The settings form hydrates from the current values, so you always start editing from the live configuration.

Three things to know before you save

A few behaviors are worth internalizing, because they are easy to get wrong:

  • Saving a field is a wholesale replace, not a merge. Submit the full redirect list to add one redirect, not just the new entry. The form hydrates from current values, which makes this natural in the console, but it matters when you script against the API.
  • The allow list is default-deny. A non-empty IP allow list blocks every address not on it. Add your own address before you save a restrictive list.
  • Basic Auth passwords are write-only. They are never echoed back when settings are read. Set a new password to change one, and leave it unchanged to keep it.

There is also a quiet rule on HSTS: preload requires include_subdomains and a max-age of at least one year, because that is what browser preload programs require. The platform rejects a preload config that does not meet it, rather than letting you submit one that no browser will honor.

Now with latency percentiles

The per-app analytics tab grew too. Alongside requests by status class, cache hit ratio, rate-limited requests per second, WAF detections by rule, and the top paths, it now shows latency percentiles: p50, p95, and p99, over selectable 15-minute, 1-hour, 6-hour, and 24-hour windows.

The percentiles are what make the WAF safe to turn up and the cache rules easy to tune. Run the WAF in detect, watch detections by rule, confirm nothing legitimate is matching, and then flip to block knowing exactly what it will reject. Add a cache rule, watch the hit ratio climb and the tail latency fall, and you can see the win instead of guessing at it.

Where it lives

Everything here is in the Domains & Edge tab on your app and behind the edge settings endpoint, with a matching GET so reads return the live configuration. The surface is wholesale-replace per field and converges across the fleet asynchronously, the same model the launch settings used. Nothing about turning this on touches your origin or asks for a redeploy.

For the full reference on each setting, the gotchas, and what the analytics show, see the Edge Settings docs. Bring a domain, set a redirect, lock down an environment, and put the WAF in block. The edge is the platform's job now, not yours.