Comparison

GraphPilot and Stellate compared

Both are managed edge caches for GraphQL APIs on Fastly's network. This page sets out what each one states about itself, with a source for every statement, and where they differ.

  • Stellate facts read on 2026-11-06
  • A source for every statement
  • Out of date? Tell us

GraphPilot

GraphPilot is a managed edge cache for GraphQL and plain HTTP APIs that purges cached responses automatically when a GraphQL mutation returns an object they contain.

Source: GraphPilot documentation

Stellate

Stellate describes itself as a platform to "Secure, Scale, and Optimize Your GraphQL APIs at the Edge", with GraphQL edge caching, metrics and security. Its acquisition post of 2024-09-10 states that The Guild is acquiring the product, will continue running Stellate's GraphQL CDN for its customers, and will gradually integrate it into the GraphQL Hive platform.

Source: Stellate blog, "Stellate has been acquired!" (2024-09-10), read 2026-11-06

At a glance

The differences people ask about first. The numbers link to each statement's source; every card also links to its full row.

When a query doesn't ask for id · 0:40
Key field injection

A query that does not select id

GraphPilot
Key fields are added on the way to the origin and removed again. [1]
Stellate
Responses are tagged with the key fields the query selects; a debug header lists entities without one. [2]
Caching that reads your schema · 1:12
Schema-driven

Where the keys live

GraphPilot
In your schema, next to the types, with @surrogateKey. [3]
Stellate
id, _id and key by default; others with keyFields in the Stellate configuration file. [4]
The empty list · 1:02
Empty-list keys

An empty list

GraphPilot
Cached, and cleared by a mutation that returns that type. [5]
Stellate
"We currently do not cache empty responses." [6]
Know which app is calling · 0:39
Client profiles

Identifying client apps

GraphPilot
A rule on a header, a verified claim or the User-Agent, with limits and a minimum version per client. [7]
Stellate
Documented for metrics: two headers, x-graphql-client-name and x-graphql-client-version. Described for rate limiting: consumers identified from any part of the request. [8]
GraphQL and REST, one cache · 0:51
GraphQL + REST

Plain HTTP next to GraphQL

GraphPilot
Both are cached. [9]
Stellate
GraphQL; its docs state non-GraphQL requests cannot be cached. [10]
Rules in one line · 0:45
Radiogram

Splitting the cache by caller

GraphPilot
Rules that combine verified JWT claims, headers, cookies and URL parameters, on the free plan too. [11]
Stellate
A claim of a JWT scope, or a function over headers and cookies. [12]

Partial query caching

GraphPilot
Not yet. [9]
Stellate
Available. [13]
Details and sources ↓

Purge speed

GraphPilot
Fastly's purge network: 150 ms on average, as Fastly states. [14]
Stellate
At most 150 ms, as Stellate states. [15]
Details and sources ↓

Security attestation

GraphPilot
No published report. [16]
Stellate
SOC 2 Type 2. [17]
Details and sources ↓

Each problem in a short clip, with a transcript: all caching problems.

In detail

Every difference with both sides' sources. Stellate statements as read on 2026-11-06.

Invalidation and keys

How a change in your data reaches the cached responses that contain it.

GraphPilot
GraphPilot adds the missing key fields to the request it sends to the origin, tags the cached response with them, and removes them before the client sees the response.
Key fields the query did not select ↗
Stellate
Its docs describe tagging a response with the key fields the query requests ("Any query that fetches an entity of type Launch and also requests the launch_name key field is then also tagged") and adding __typename to the query sent to the origin. The gcdn-missing-id-paths header lists "Entities included in the response that are missing a way to identify them uniquely, e.g. because the query doesn't ask for id or another configured key field." Adding missing key fields is not described in the docs as read on 2026-11-06.
Stellate docs, Stellate headers ↗ Stellate docs, response tagging ↗ Stellate docs, switching to the new infrastructure ↗

Caching

What is cached, who shares an entry, and how you see why something was not cached.

GraphPilot
Policy expressions (Radiogram), an expression language that reads verified JWT claims next to headers, cookies and URL parameters, joins them, and normalizes them with functions (lower, upper, split, membership, version comparisons, pseudonymize); the deployment warns about a negation a request could leave undecided. On every plan, Glider (Free) included.
Policy expressions ↗
Stellate
A JWT scope names the claim to scope by (claim: 'sub'). Dynamic scopes run a function from the configuration file over the request's headers and cookies; a JWT read there is checked in the function: "you need to validate it manually inside your function". "This feature is not available on the free plan."
Stellate docs, scopes ↗
GraphPilot
Every request, unless telemetry.record, a policy expression, narrows it (leaving out health probes, for example) or turns it off; a request left out is still served and billed. The client IP address is kept in full, truncated or not at all.
Recording only some requests ↗
Stellate
Query metadata is anonymized: "we do not store variables", and hard-coded arguments are turned into variables before a query is stored.
Stellate docs, query anonymization ↗

Security

Verifying callers and protecting the origin.

GraphPilot
Client profiles: a policy expression on a header, a verified claim or the User-Agent names the client and reads its version. Each client can get its own limits, a minimum version below which it is refused at the edge, or no caching.
Client profiles ↗
Stellate
Stellate documents this for metrics with two headers: "Stellate infers the client from headers that you should include in every request: x-graphql-client-name, x-graphql-client-version." For rate limiting, its product page describes "Different limits for different consumers", with consumers identified "by any part of the request".
Stellate docs, client tracking ↗ Stellate, GraphQL Rate Limiting ↗
GraphPilot
Not yet. There is no limit on requests in flight or requests per second; the edge limits query depth, selections, document size and body size instead.
Limits ↗
Stellate
Stellate's docs and product page describe Rate Limiting (request-based, and complexity-based "Currently in Alpha"), and its current pricing page still lists it ("Rate Limiting + $5" per 1M requests on the Business plan), as read on 2026-11-06. Earlier, the acquisition post of 2024-09-10 announced: "The Developer Portal and Rate Limiting products will be sunset in two months." The pages read do not say whether that plan was carried out.
Stellate docs, Rate Limiting quickstart ↗ Stellate pricing ↗ Stellate, GraphQL Rate Limiting ↗ Stellate blog, "Stellate has been acquired!" (2024-09-10) ↗

Network, plans and company

Where it runs, what it costs to start, and who runs it.

GraphPilot
Glider (Free): 100,000 request units a month. A request unit is counted per started 10 KiB of response body at each point of presence, so it is not the same unit as a request.
GraphPilot pricing ↗
Stellate
Free: "Up to 100k requests / mo", "Fair use policy applies".
Stellate pricing ↗

Plan scope and billing models differ (GraphPilot: request units and recorded requests, in EUR; Stellate: requests per product, in US dollars), so these prices are not a like-for-like comparison.

GraphPilot
Jet (Starter): 149 EUR a month, net, billed monthly, with 500,000 request units and 10M recorded requests (Insights) a month included; above that, 6 EUR per started 1M request units and 12 EUR per started 1M recorded requests.
GraphPilot pricing ↗
Stellate
Business: "Starts at $249 / month", "25M metrics requests included / mo", "Additional requests: $10 / mo per 1M requests"; edge caching and rate limiting are billed per 1M requests on top ("+ $5" each).
Stellate pricing ↗

Plan scope and billing models differ (GraphPilot: request units and recorded requests, in EUR; Stellate: requests per product, in US dollars), so these prices are not a like-for-like comparison.

What GraphPilot does not do

Stated up front, so you don't have to find out later.

Moving from Stellate to GraphPilot

The concepts map as follows. The full checklist for moving traffic is in Coming from another CDN.

Frequently asked questions

Do my queries have to select id for invalidation to work?
No. When a query does not select the key fields of an object, GraphPilot adds them to the request it sends to the origin, tags the cached response with them and removes them before the client sees the response.
Is GraphPilot a drop-in replacement for Stellate?
No configuration carries over as is. Cache lifetimes move to @cacheControl or Cache-Control headers, scopes to GraphPilot's private policy, named scopes or vary rules, and clients point at the GraphPilot service URL. Partial query caching has no equivalent yet.
Does GraphPilot purge cached responses after a mutation?
Yes. A mutation purges the cached responses that contained the objects it returned. To make a created item appear in a cached list, the list carries a key that the create's response names.
Do GraphPilot and Stellate run on the same edge network?
Both state that they run on Fastly's edge network.
Can GraphPilot be tried without paying?
Yes. Glider (Free) needs no credit card. It is meant for trying GraphPilot out, development, testing and small projects, not for production.
Does GraphPilot support rate limiting?
Not yet. Today it refuses GraphQL operations over its depth, selection, document size and body size limits before they reach the origin, but it does not limit how many requests a client sends.

Sources

Stellate statements come from Stellate's own pages, read on 2026-11-06. GraphPilot statements come from the GraphPilot documentation and this site.

Cleared for takeoff

Start on Glider (Free).
No credit card, no commitment.

Prefer to talk first? Book a call