Edge locations
GraphPilot runs on Fastly’s global edge network. A request is routed to a nearby location, handled there, and answered from there when the cache can answer it. There is nothing to configure: routing is handled for you and the set of locations may change over time.
The cache is per location
Section titled “The cache is per location”This is the part worth internalizing, because it shapes what hit rate you should expect.
Each edge location holds its own cache. A response stored in Frankfurt is not stored in
Singapore. The first request for an operation at each location is a MISS and goes to your
origin, however many times the same operation has been served elsewhere.
All of this holds unless you switch on shielding, which is off by default. With shielding, one location’s cache stands between every other location and your origin.
Two consequences follow:
- Your hit rate depends on how your traffic is distributed. An operation requested a thousand times an hour from one region hits nearly always. The same operation requested once an hour from thirty regions may never hit at all, because each entry expires before that location sees a second request. Traffic concentration, not total volume, is what makes a cache work.
- Origin load falls by less than your hit rate suggests at first. Steady state is what matters; the warm-up is paid once per location per entry.
If an operation is expensive and rarely requested, a longer freshness lifetime is the lever: it gives each location’s entry more chances to be reused. See how long an entry lives.
If your audience is spread across many regions, shielding is the other lever: it pays the warm-up once for the whole network instead of once per location.
Shielding
Section titled “Shielding”Shielding routes cache misses through one edge location, the shield, before they reach your origin. Every location asks the same shield, so its cache is in effect shared by the whole network and your origin sees about one miss per entry per lifetime, however many locations request it. Each location still keeps its own copy, so a request is still answered from nearby once its location has the entry. It is optional and off by default, and used on paid plans. Name the shield location closest to your origin:
[origin]shield = "eu-frankfurt"How a shielded request flows, which requests go through the shield, what happens when it cannot be used, and what it costs in request units are on shielding.
Shield locations
Section titled “Shield locations”The shield setting takes one of these values. Each one is named <region>-<city>. London and
Sydney have more than one location, so their values carry a third part; any of them works. Pick
the location closest to your origin. It is also where the shared copy of your cached responses
is kept (see where data lives). A value that is not in this list refuses
the deployment. When it looks like a typo of a known value, the message suggests up to three values to use instead.
| Value | City | Country | Region |
|---|---|---|---|
af-capetown | Cape Town | ZA | Africa (af) |
af- | Johannesburg | ZA | Africa (af) |
ap-auckland | Auckland | NZ | Asia-Pacific (ap) |
ap-brisbane | Brisbane | AU | Asia-Pacific (ap) |
ap-chennai | Chennai | IN | Asia-Pacific (ap) |
ap- | Christchurch | NZ | Asia-Pacific (ap) |
ap-delhi | Delhi | IN | Asia-Pacific (ap) |
ap-hongkong | Hong Kong | HK | Asia-Pacific (ap) |
ap-hyderabad | Hyderabad | IN | Asia-Pacific (ap) |
ap-kolkata | Kolkata | IN | Asia-Pacific (ap) |
ap-melbourne | Melbourne | AU | Asia-Pacific (ap) |
ap-mumbai | Mumbai | IN | Asia-Pacific (ap) |
ap-osaka | Osaka | JP | Asia-Pacific (ap) |
ap-perth | Perth | AU | Asia-Pacific (ap) |
ap-seoul | Seoul | KR | Asia-Pacific (ap) |
ap-singapore | Singapore | SG | Asia-Pacific (ap) |
ap- | Sydney | AU | Asia-Pacific (ap) |
ap- | Sydney | AU | Asia-Pacific (ap) |
ap-tokyo | Tokyo | JP | Asia-Pacific (ap) |
ca-montreal | Montreal | CA | Canada (ca) |
ca-toronto | Toronto | CA | Canada (ca) |
eu-amsterdam | Amsterdam | NL | Europe (eu) |
eu-brussels | Brussels | BE | Europe (eu) |
eu- | Copenhagen | DK | Europe (eu) |
eu-dublin | Dublin | IE | Europe (eu) |
eu-frankfurt | Frankfurt | DE | Europe (eu) |
eu-helsinki | Helsinki | FI | Europe (eu) |
eu-lisbon | Lisbon | PT | Europe (eu) |
eu- | London | GB | Europe (eu) |
eu- | London | GB | Europe (eu) |
eu- | London | GB | Europe (eu) |
eu-madrid | Madrid | ES | Europe (eu) |
eu- | Manchester | GB | Europe (eu) |
eu-marseille | Marseille | FR | Europe (eu) |
eu-milan | Milan | IT | Europe (eu) |
eu-oslo | Oslo | NO | Europe (eu) |
eu-paris | Paris | FR | Europe (eu) |
eu-sofia | Sofia | BG | Europe (eu) |
eu-stockholm | Stockholm | SE | Europe (eu) |
eu-vienna | Vienna | AT | Europe (eu) |
me-fujairah | Fujairah | AE | Middle East (me) |
sa-bogota | Bogota | CO | South America (sa) |
sa- | Rio de Janeiro | BR | South America (sa) |
sa-saopaulo | Sao Paulo | BR | South America (sa) |
us-ashburn | Ashburn | US | United States (us) |
us-atlanta | Atlanta | US | United States (us) |
us-boston | Boston | US | United States (us) |
us-chicago | Chicago | US | United States (us) |
us-dallas | Dallas | US | United States (us) |
us-denver | Denver | US | United States (us) |
us-houston | Houston | US | United States (us) |
us- | Los Angeles | US | United States (us) |
us-miami | Miami | US | United States (us) |
us- | Minneapolis | US | United States (us) |
us-newyork | New York City | US | United States (us) |
us-newark | Newark | US | United States (us) |
us-portland | Portland | US | United States (us) |
us-sanjose | San Jose | US | United States (us) |
us-seattle | Seattle | US | United States (us) |
Purging is global
Section titled “Purging is global”Invalidation does not have this property. A purge, whether it came from a mutation, the API or the CLI, removes the entry at every location, not only the one that served the request that triggered it.
That asymmetry is deliberate and is the point of surrogate keys: entries are cheap to create per location and must be removable everywhere at once, or invalidation could not be relied on.
With shielding, a purge clears the entry at the shield too, because purges are global. A purge through the API, the CLI or the portal on a shielded service is sent a second time shortly after the first; see mutations and purges.
Where data lives
Section titled “Where data lives”This section covers data location and data residency. Two different things are stored in two different places, and the distinction matters for a data protection (GDPR) review.
Cached responses
Section titled “Cached responses”A cached response lives in Fastly’s cache at the locations that served it, worldwide. It is stored as the bytes your origin produced, plus the metadata needed to serve it again: its lifetime, its surrogate keys, and the discriminators it is partitioned by.
The discriminator values themselves are not stored with the response, and neither is the credential the request carried.
There is no region pinning and no data-residency guarantee for cache entries. A response is
held wherever it was requested from. If a class of data must not leave a region, do not make it
cacheable: mark it no-store at your origin, or exclude it with a
bypass.
With shielding, an entry is also stored at the shield location, whichever location requested it. A shield in the EU keeps that shared copy in the EU; the copies at the requesting locations stay where they are. Take the shield location into account in a data protection review.
Telemetry and logs
Section titled “Telemetry and logs”Request telemetry is stored under the rules on what Insights
needs. A request that was not stored is still counted for usage, but no record of it is kept, so there
is nothing to look up in Insights and nothing for
purgeByRequest to resolve.
When it is stored, request telemetry is kept in the EU for at most 90 days. How far
back you can look in Insights depends on your plan: 1 day on Glider (Free), 7 days on Jet, 30
days on Airliner and 90 days on Jumbo, after which a request is deleted. See what Insights
needs. Once a request is no longer stored, it can no longer
be resolved, which is also what bounds purgeByRequest.
What is recorded about each request is yours to configure, and the defaults are narrow:
authorization and cookie are replaced by a keyed digest rather than stored, and only a
handful of descriptive headers are kept. See [telemetry].
The raw telemetry copy
Section titled “The raw telemetry copy”Each recorded request and its log lines are also written to files in GraphPilot’s raw telemetry store, held in Google Cloud Storage in the EU, so Insights can be rebuilt after a loss.
- They hold the same record Insights does: the request’s telemetry row and its log lines,
including the client IP address and the geo and network data looked up from it, the captured
headers and the GraphQL document.
telemetry.client_ipis applied at the edge before anything is written, so on a"truncated"or"none"service the files never hold the full address either. A request that is not recorded is not in them. - Each file is kept for at most 90 days after it was written, then deleted automatically. The files are protected against deletion for part of that period, so a mistake or an incident cannot remove the copy.
- Deleting a service, an organization or your account does not delete these files early. The service’s Insights data is removed from the Insights database within minutes; its files stay until their 90 days run out. This is a deliberate exception: deleting them earlier would mean deleting the copy that protects everyone else’s Insights data.
- They are used for nothing else. They are not readable through the portal, the CLI or the GraphPilot API, and are read only to fill and rebuild Insights. A rebuild deletes again the data of every service, organization and account that was deleted in the meantime.
- There is no further copy of the files. They are not included in any other backup.
- The Insights database has backups of its own, taken daily by its provider and kept for 30 days. Data removed from the database stays in those backups until they expire.
What a deletion keeps
Section titled “What a deletion keeps”Deleting a service, an organization or an account removes its telemetry, logs and stored files within minutes, once each service is off the edge. These records are kept on purpose:
- The request counts usage is billed from, and the billing and invoice history, which GraphPilot is required to keep.
- The record of the terms an organization accepted: which version, when, and by whom, with the email address and name the accepting user’s login had at that moment. It is kept as evidence of the contract, also once that login is deleted.
- The raw telemetry copy, for at most 90 days after each file was written, used only to rebuild Insights data.
- Database backups, overwritten within 35 days, and backups of the Insights database, kept for 30 days.
- For an account: the record of your calls to the GraphPilot API from the portal and the CLI, for at most 90 days.
Resetting a service’s history keeps the same records, and also the measurements alerting compares against, because the service goes on running.
Latency
Section titled “Latency”Serving from a nearby location is most of where the latency saving comes from, and how much you gain depends on the distance between your users and your origin rather than on the cache alone. Performance and benchmark methodology explains what is measured, how, and how to reproduce it.
Custom domains
Section titled “Custom domains”A custom domain is served from the same network as the service hostname, with a certificate issued for it. Attaching one changes nothing about routing, caching or invalidation.