Quickstart: HTTP
This takes you from a new account to a verified cache HIT in front of your own HTTP API, and
then shows a purge clearing that entry. Nothing here is throwaway: the service you create and the
config you write are the ones you keep. If your origin is a GraphQL API, follow the GraphQL
quickstart instead; it adds caching and invalidation from your
schema.
Before you start you need an HTTP API that GraphPilot can connect to over the internet, and
the ability to change the response headers it sends. It does not have to be public. The examples
use GET /products/42 and PUT /products/42; substitute an endpoint from your own API.
-
Get an account and the CLI
Section titled “Get an account and the CLI”Sign up at cockpit.graphpilot.io and create an organization with New organization if you do not belong to one yet; the dialog asks you to accept the Terms of Service. Then install the
gpilotCLI and log in:Terminal window brew install graphpilot/tap/gpilotgpilot auth loginOther platforms: installing the CLI. Several organizations or identities: signing in.
-
Create the service
Section titled “Create the service”A service is one origin behind GraphPilot, with its own hostname, configuration and cache.
In the portal, choose New service on your organization’s page. The Create a new service dialog asks for a Service name (
Catalog API), an Origin URL (https://api.internal.example.com, the URL of your HTTP API), a Subdomain (catalog-api) and an Environment. See creating a service for what each field accepts. Keep Deploy right away (no schema, default configuration) ticked.Select Create service. The next dialog shows the service’s signing key, once. Copy it into your secret manager, then select I have copied the key.
The service’s dashboard now shows Setting up catalog-api: GraphPilot deploys the service once as a plain pass-through with every setting at its default, then checks for a GraphQL API behind it. For a REST or plain HTTP origin it finds none and says No GraphQL endpoint detected, the service runs as plain HTTP; select Keep as plain HTTP to finish. See set up a new service.
Then select the service in the CLI:
Terminal window gpilot service select catalog-apiTerminal window gpilot service create \--name "Catalog API" \--url https://api.internal.example.comgpilot service select catalog-apiThe subdomain is derived from the name unless you pass
--subdomain. The command prints the service’s signing key once, in the Signing key row; copy it into your secret manager then. GraphPilot never shows it again. See the signing key.The command asks
Deploy right away?; answer yes (the default). It then follows the same setup as the portal, finds no GraphQL behind a REST or plain HTTP origin, and asksKeep the service as plain HTTP?: answer yes.--deploy --keep-plain-httpanswers both up front; seegpilot service create.Once the first deployment is live, your service is reachable at
https://catalog-api.k7m2qp.graphpilot.cloud(k7m2qpstands for your organization’s hostname label, which the portal shows). That takes one to two minutes, and for your organization’s first service a few minutes more, up to an hour, while its certificate is issued; the setup shows both. GraphPilot forwards each request to your origin’s host with the path and query string the client sent, sohttps://catalog-api.k7m2qp.graphpilot.cloud/products/42reaches/products/42on your origin. How the origin URL is used (scheme, port, TLS) is on origin. -
Write a config
Section titled “Write a config”In the directory you will deploy from, create
gpilot.toml. Every setting has a default, so an empty file is valid, and a plain HTTP origin needs nothing else to start:gpilot.toml # Nothing here is required. See /reference/configuration for every setting. -
Send Cache-Control and a surrogate key from your origin
Section titled “Send Cache-Control and a surrogate key from your origin”GraphPilot does not decide on its own that a response may be reused. Your origin says so. Add two headers to the response for
GET /products/42:HTTP/1.1 200 OKContent-Type: application/jsonCache-Control: s-maxage=60Surrogate-Key: product-42 productsCache-Control: s-maxage=60lets GraphPilot keep the response for 60 seconds and share it between callers; see when a response is cached for every directive it reads.Surrogate-Keytags the entry with keys you choose, so you can purge it by name later. GraphPilot removes that header before the response reaches the client. The format is on the Surrogate-Key header.Each entry is keyed by the request method and the path, query string included, so
/products/42?lang=deis a separate entry. The hostname is not part of the key. -
Deploy
Section titled “Deploy”Deploy the config on its own. A plain HTTP service needs no schema. The setup already runs the service on the defaults, so nothing changes in behavior while the file is empty, but from here on the service runs on a configuration you keep in your repository, and the dashboard’s checklist counts this deployment as your own:
Terminal window gpilot deployThis picks up
./gpilot.toml, shows what changed since the last deployment, and asks before uploading anything. With noschema.graphqlorschema.gqlin the directory, it says so before it asks:No schema found: deploying as a plain HTTP service, GraphQL features are off.That is the expected line for this origin, not an error. It then waits for the deployment to go live, printing each step and any findings the build reported, including a notice that the service has no schema. A failed build never goes live. Flags for CI, other paths and not waiting are in the command reference.
If the same origin also serves a GraphQL API, deploy it with that schema instead, by following the GraphQL quickstart: requests to its other paths are plain HTTP and get everything on this page.
-
Verify the cache
Section titled “Verify the cache”Send the same request twice to your service hostname:
Terminal window export GRAPHPILOT_HOST=catalog-api.k7m2qp.graphpilot.cloudcurl -sS -D- -o/dev/null "https://$GRAPHPILOT_HOST/products/42" | grep -i '^gp-'The first response is a
MISS: it came from your origin and was stored. The second is aHIT:gp-cache: HITgp-cache-hits: 1gp-cache-age: 4gp-cache-max-age: 60gp-cache-remaining: 56If you see
PASS, read the next section. -
Purge by key
Section titled “Purge by key”Clear every response tagged
product-42:Terminal window gpilot purge product-42The command shows what it is about to purge and asks you to confirm. Repeat the request from step 6: the first response is a
MISSagain, and the one after it is aHIT. A purge reaches every edge location. To clear one response without a key of your own, purge its cache key,ck:GET:/products/42, the method and the path without scheme or hostname. See the purge API for every way to purge.Your origin can also purge without any call. When the response to a write carries
Surrogate-Key, GraphPilot purges the keys it names instead of tagging:HTTP/1.1 200 OKSurrogate-Key: product-42Send that on your origin’s response to
PUT /products/42(or anyPOST,PUT,PATCHorDELETE) through GraphPilot, and the nextGET /products/42is aMISS. See the Surrogate-Key header.
If you see PASS
Section titled “If you see PASS”gp-cache: PASS means the response was not stored, and gp-cache-reason names the rule that
refused. These three cause most first-deployment misses:
- Your origin sets a cookie (
CACHE_SKIPPED_SET_COOKIE). A response that sets a session cookie is never stored. Frameworks that touch the session on every request do this by default. See the refusals. - The response has no lifetime (
CACHE_SKIPPED_NO_CACHE_POLICYorCACHE_SKIPPED_NO_MAX_AGE). Check that your origin’s response carriess-maxageormax-age, and that nothing between your application and GraphPilot replaced the header. - The request carried a credential (
CACHE_SKIPPED_CREDENTIALED_REQUEST). A request with anAuthorizationheader, a cookie that is not on your cookie allow list, or the header an auth provider reads is only shared when the response says so withpublicors-maxage. For answers that differ per caller, see identifying callers and authenticated requests.
Every other reason is in why is nothing cached?, and a second
MISS where you expected a HIT in
troubleshooting.
Point your clients at it
Section titled “Point your clients at it”Change your clients’ base URL to the service hostname, keeping your paths. Nothing else changes:
what reaches your origin is the same request, with a signature added and Accept-Encoding: identity (GraphPilot compresses the response for the client itself).
const response = await fetch("https://catalog-api.k7m2qp.graphpilot.cloud/products/42");const product = await response.json();Before you consider this finished, verify the request signature at your origin, so it only trusts traffic that came through GraphPilot, and keep your origin’s clock in sync, because the signature is time-bound. Both are on the go-live checklist.
Where to go next
Section titled “Where to go next”| You want to | Read |
|---|---|
| Understand exactly what gets cached and what does not | When a response is cached |
| Tag, partition and purge a whole REST API | Caching a REST API |
| Cache answers that differ per caller or per organization | Who shares an entry |
| See which features apply to plain HTTP | Features and limitations |
| Clear something by hand or from a job | The purge API |
| Deploy from a pipeline | Deploy from CI |
| See every setting | Configuration reference |
| Serve it on your own hostname | Custom domains |