Skip to content

Commit a190c65

Browse files
authored
Add docs for fly-replay-cache (#2011)
* Add docs for fly-replay-cache * fixup * Add replay caching to the per-user dev environment blueprint * Update * Update
1 parent 500bc50 commit a190c65

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

blueprints/per-user-dev-environments.html.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ This blueprint explains how to use Fly Machines to securely host ephemeral devel
1616
Your architecture should include:
1717

1818
- **Router app(s)**
19-
- A Fly.io app to handle requests to wildcard subdomains (`*.example.com`). Uses `fly-replay` headers to transparently redirect each request to the correct app and machine. If you have clusters of users (or robots) in different geographic regions, you can spin up a router app in multiple regions (you might also want to consider a globally distributed datastore like [Upstash for Redis](https://fly.io/docs/upstash/redis/#what-you-should-know)).
19+
- A Fly.io app to handle requests to wildcard subdomains (`*.example.com`). Uses `fly-replay` headers to transparently redirect each request to the correct app and machine. If you have clusters of users (or robots) in different geographic regions, you can spin up a router app in multiple region to increase reliability and reduce latency (you might also want to consider a globally distributed datastore like [Upstash for Redis](https://fly.io/docs/upstash/redis/#what-you-should-know)).
2020
- **User apps (pre-created)**
2121
- Dedicated per-user (or per-robot) Fly apps, each containing isolated Fly Machines. App and Machine creation is not instantaneous, so we recommend provisioning a pool of these before you need them so you can quickly assign upon request.
2222
- **Fly Machines (with optional volumes)**
@@ -32,7 +32,8 @@ Your router app handles all incoming wildcard traffic. Its responsibility is sim
3232

3333
- Extract subdomains (like `alice.example.com``alice-123`).
3434
- Look up the correct app (and optionally machine ID) for that user.
35-
- Issue a `fly-replay` header directing the Fly Proxy to [internally redirect the request](https://fly.io/docs/networking/dynamic-request-routing) (this should add no more than ~10 milliseconds of latency).
35+
- Issue a `fly-replay` header directing the Fly Proxy to [internally redirect the request](https://fly.io/docs/networking/dynamic-request-routing) (this should add no more than ~10 milliseconds of latency if the router app is deployed close to the user).
36+
- When appropriate, use [replay caching](https://fly.io/docs/networking/dynamic-request-routing/#replay-caching) to further reduce latency and load on the router app.
3637
- Make sure you've added [a wildcard domain](https://fly.io/docs/networking/custom-domain/#get-certified) (*.example.com) to your router app (read more about the [certificate management endpoint here](https://fly.io/docs/networking/custom-domain-api/)).
3738

3839
### User apps

networking/dynamic-request-routing.html.markerb

+28
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,26 @@ You can combine multiple fields:
5555
fly-replay: region=sjc;app=app-in-same-org
5656
```
5757

58+
## Replay Caching
59+
60+
In cases where the replay target does not change often, you can use the `fly-replay-cache` mechanism to relieve the original app of some load. Here's how it works:
61+
- Issue a `fly-replay` header as usual
62+
- Set `fly-replay-cache: example.com/some/path/*`
63+
- This needs to be a path-matching pattern ending with a wildcard `/*`. This is where the cached replay is applied.
64+
- The domain part should not include ports; use `example.com`, not `example.com:80`.
65+
- The pattern must also match the current path of the request.
66+
- Set `fly-replay-cache-ttl-secs: number_of_seconds`
67+
68+
If the replay target does eventually change, the replay target may proactively invalidate the cache by
69+
- Issuing a `fly-replay` back to the origin
70+
- Setting `fly-replay-cache: invalidate`
71+
72+
<div class="note icon">
73+
**Note**: Replay caching is an optimization, not a guarantee. Your app should _not_ depend on this mechanism to function.
74+
The app issuing `fly-replay` still serves as the ultimate source of truth, and we may decide to consult that app at any moment even if a replay cache has previously been set.
75+
To ensure reliable operation, the app issuing `fly-replay` should still have multiple instances deployed in multiple regions.
76+
</div>
77+
5878
## Implementation Details
5979

6080
### Requirements and Limitations
@@ -67,6 +87,12 @@ For large uploads that exceed the 1MB limit, consider:
6787
- Using direct-to-storage uploads where possible
6888
- Using the [fly-prefer-region](#the-fly-prefer-region-request-header) header instead
6989

90+
For `fly-replay-cache`, the following limitations apply:
91+
- The `state` field cannot be set in the `fly-replay` intended to be cached
92+
- The TTL needs to be a minimum of 10 seconds
93+
- Only one step of lookup is performed in the cache; as such, if the target app issues another `fly-replay-cache`, the caching behavior in this case is undefined
94+
- The `fly-replay-src` header (described below) will _not_ be set for requests replayed through the cache
95+
7096
### The fly-replay-src Header
7197

7298
When a request is replayed, Fly Proxy adds a `fly-replay-src` header containing metadata about the original request:
@@ -80,6 +106,8 @@ When a request is replayed, Fly Proxy adds a `fly-replay-src` header containing
80106

81107
This header is useful for tracking request paths and implementing consistency patterns. See the [official Ruby client](https://github.com/superfly/fly-ruby/blob/main/lib/fly-ruby/regional_database.rb#L74-L76+external) for an example of using these fields to prevent read-your-write inconsistency.
82108

109+
This header is not set when the request is replayed through a cached `fly-replay` entry (`fly-replay-cache`).
110+
83111
## Alternative Routing Headers
84112

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

0 commit comments

Comments
 (0)