Dynamic Request Routing with fly-replay

The fly-replay header is a powerful feature that gives you fine-grained control over request routing in your Fly.io applications. It allows you to dynamically route requests between regions, specific Machines, or even different apps within your organization.

How fly-replay Works

When your app adds a fly-replay header to a response, Fly Proxy will automatically replay the original request according to your specified routing rules. This enables advanced patterns like:

  • Routing write operations to primary database regions
  • Load balancing between specific Machines
  • Cross-app request routing within your organization
  • Implementing sticky sessions

Header Fields Reference

The fly-replay header accepts the following fields:

Field Description
region The 3-letter code for the region to route the request to
instance The ID of a specific Machine to route to
app The name of another app (in same organization) to route to
state Optional string included in fly-replay-src header on replay
elsewhere If true, excludes responding Machine from next load-balance

Example Usage

Route to specific region:

fly-replay: region=sjc

Route to specific Machine:

fly-replay: instance=00bb33ff

Route to another app:

fly-replay: app=app-in-same-org

You can combine multiple fields:

fly-replay: region=sjc;app=app-in-same-org

Implementation Details

Requirements and Limitations

  • Your app must use the http handler
  • Requests larger than 1MB cannot be replayed
  • Field combinations must be logically valid (e.g., don’t specify both app and instance if instance isn’t in that app)

For large uploads that exceed the 1MB limit, consider:

  • Using direct-to-storage uploads where possible
  • Using the fly-prefer-region header instead

The fly-replay-src Header

When a request is replayed, Fly Proxy adds a fly-replay-src header containing metadata about the original request:

Field Description
instance ID of Machine that sent fly-replay
region Region request was replayed from
t Timestamp (microseconds since Unix epoch)
state Contents of original state field, if any

This header is useful for tracking request paths and implementing consistency patterns. See the official Ruby client for an example of using these fields to prevent read-your-write inconsistency.

Alternative Routing Headers

For cases where fly-replay isn’t suitable, Fly.io provides two alternative request headers:

The fly-prefer-region Header

fly-prefer-region: ams

Attempts to route directly to a specific region. Falls back to nearest region with healthy Machines if target region is unavailable. Useful for large uploads that can’t be replayed.

The fly-force-instance-id Header

fly-force-instance-id: 90801679a10038

Forces routing to a specific Machine. No fallback if Machine is unavailable.

Note: Get Machine IDs using fly status or fly Machines list.

Common Use Cases

Multi-Region Databases

When using global read replicas, use fly-replay to ensure write operations go to the primary region:

fly-replay: region=sjc

See our blueprint for Multi-region databases and fly-replay for a complete implementation guide.

Cross-App Routing

Use fly-replay to implement routing layers or FaaS-style architectures:

fly-replay: app=customer-function-app

This allows you to build router apps that can dynamically route requests to other apps in your organization.