Skip to content

Schema and config findings

The Schema and Config sections of a service show what is live: the schema and the configuration of the deployment that is serving traffic, what GraphPilot made of them, and what it found wrong. They answer “what does my service do right now” without you having to find the right deployment first.

Every deployment’s own page under Deployments shows the same findings for that deployment. What each finding means is in deployment diagnostics. In the portal, both sections need the deployment:view permission; through the API, the live deployment’s analysis on the service needs only service:view (see permissions). gpilot deploy prints the deployment’s diagnostics (schema and configuration) when it finishes, unless run with --detach. The Keys that do nothing list under Config → Findings is shown only in the portal and on the GraphPilot API.

Open a service and choose Schema. It has six views.

ViewAnswers
ExplorerWhat is in your API: every type and field, with the cache rules and surrogate keys that apply to each.
Cache rulesWhat will be cached and for how long. Each rule shows Where it is declared, how long it is Cached for and How it applies. A schema with no hints says so, with the default freshness lifetime (TTL) every response gets.
Surrogate keysWhich keys responses are tagged with, where each comes from, and which mutations can throw a cached answer away. Keys can be copied, and purged from here.
OperationsWhat one call does to the cache: for a query, the keys its cached answer carries and which mutations can throw it away; for a mutation, what it purges and which cached reads that reaches.
FindingsWhat the deployment build refused or warned about. See below.
schema.graphqlThe exact schema that was deployed. Select a line number to copy a link to that line.

The sidebar shows how many items each view holds, and a badge on Schema when the live build has findings.

Wherever a surrogate key is listed, it can be copied and, with the cache:purge permission, purged; see purging from other pages.

The list on the left holds every definition, grouped by kind (each group folds away). Above it:

  • Filter types (“Filter types and fields…”) narrows the list by name.
  • Sort types: In the document, A to Z, Annotated first or Problems first.
  • Three filters, one per mark a row can carry: Cache rules, Surrogate keys and Findings. Each keeps the types that have it, or those that do not; an active one shows as a chip such as “no cache rules”. Selecting a mark on a row shows only the types with that mark.

Select a type to read it. Its detail shows the definition, as Type (the structured view) or as its source in schema.graphql, with a copy button and Previous type and Next type. Below it:

  • Cache rules: how long a response holding this type is cached, and where that comes from. Without a rule, it says the schema’s default applies.
  • Surrogate keys: which keys this type puts on a response, from your annotations or from GraphPilot’s defaults, including the keys it inherits from its interfaces and unions, each under the interface or union and under the type itself (Medium:isbn:{isbn} and Book:isbn:{isbn}). Without one, a cached response holding it can only be thrown away by waiting out its TTL or by purging everything, and the panel says so. Each key carries a mark: a bolt for a key a mutation can purge (dynamic), a hand for a key nothing purges on its own (fixed). A dynamic key that no mutation in the schema can return also gets the hand.
  • Can be purged by: shown when the type has a dynamic key. It names each mutation that can reach this type and how: it returns the type (“returns it”), the client selects the path to it (“when the client selects products”), or GraphPilot adds that path to every call. A mutation purges only the keys its own response carries, so each call purges the objects it actually returned. When no mutation returns the type, directly or through anything it returns, the panel says so: purge its keys by hand, through the purge API, or by naming them in a Surrogate-Key header on a mutation’s response.
  • What this mutation purges: shown on a type a mutation returns (a mutation payload type), in the same blocks as on a mutation in Operations.
  • Referenced by: the types and fields that point to this one.

On the query and mutation root types, Keys at runtime points to Open Operations instead, where each root field is answered as its own operation.

The list on the left holds every operation, grouped into Queries, Mutations and Subscriptions; Filter operations narrows it by name. A query or mutation that reaches nothing on the other side carries a red mark: a mutation whose keys no cached read is tagged with, or a query no mutation can throw away. Before you select one, the page counts how many operations are marked.

Select an operation to see what one call does to the cache. Its header names the type it Answers with, which opens that type in the Explorer. Below it, a summary strip:

  • for a query, Carries (how many keys its cached answer carries), Cleared by (how many mutations can throw it away) and Kept for (the cache rule on the field or its return type, or the schema default);
  • for a mutation, Purges (how many keys it purges) and Reaches (how many cached reads that can reach).

A count of zero under Cleared by or Reaches shows in red.

What the cached answer carries (for a query) or What this mutation purges (for a mutation) lists those keys in blocks:

  • Always: carried by every call, whatever the client selected.
  • From the selection: carried only where the client selected the type that declares them, one selection step from what the operation returns.
  • Injected (mutations only): keys the proxy adds whatever the client asked for, so the entity the mutation changed stays purgeable even from a response that only acknowledges the write. A note gives the surrogate_key.mutation_payload_depth the descent ran at, and how many more paths one level deeper would reach.

Then, for a query, What can throw this away lists the mutations that produce a key its cached answer carries; for a mutation, What this reaches lists the cached reads tagged with a key it produces. Each row shows how many keys the two share, expands to list them, and links to that operation. A shared key still only throws away the entries whose values also match, so the list says which operations can be reached, not what every call reaches. With more than six rows, Filter by operation or key narrows the list.

When the list is empty, the panel says what that means. For a query: “No mutation in this schema produces a key this answer is tagged with. Once it is cached it stands until its age runs out, whatever happens to the data behind it.” For a mutation: “Nothing this API caches is tagged with anything this mutation produces.” A client reading the same data after the mutation then gets the answer from before the write until that entry expires.

A subscription is not cached, so its page says Nothing to cache, nothing to purge.

Schema → Findings lists the diagnostics the build of the live deployment recorded. Each finding has a severity (error, warning or notice), the part of the build that reported it, a message, and the line and column in your schema. Filter by severity and by source, or search the messages. A finding’s line links into schema.graphql, and the type it sits in links into the Explorer.

An error means the build refused something, for example a @surrogateKey whose selection path does not exist. A warning means it built, but probably not the way you intended. Fix the schema and deploy again. What each diagnostic means is in deployment diagnostics.

On Findings, a service that has never gone live says Nothing has been built yet.

When the live deployment has no schema, the service is plain HTTP and GraphQL features are off. Explorer, Cache rules, Surrogate keys, Operations and schema.graphql then show one of two states instead of an empty page, decided by whether a schema was ever uploaded:

  • No schema stored yet: the service is serving plain HTTP, so there are no types, cache rules, surrogate keys or operations to show. It offers New deployment (with deployment:edit) and the command gpilot deploy to run next to your schema.graphql, and, to read the schema from your running API, gpilot schema pull.
  • A schema was uploaded but is not live: a schema was uploaded on the date shown, but the service is serving plain HTTP until a deployment with it goes live. Deploy it opens the New deployment dialog.

The header still names the deployment that is live and links to it. A service with nothing live at all, such as one created without Deploy right away, shows the same two states, saying that nothing is deployed yet; after a failed or canceled deployment it shows the panel that points to that deployment instead. Deploy with a schema to fill the views in.

Findings still lists what the build recorded, because a deployment without a schema is still checked against its configuration: the notice that it has no schema, and configuration findings such as the error for a request.graphql_paths that is set but ignored. A notice is a third severity beside error and warning. It asks for nothing, the Notices button appears only when there is one, and it is never counted in the badge on Schema.

Open a service and choose Config. It has three views.

A deployment without a configuration file (see Default configuration in starting a deployment) runs on the defaults. The header then reads Default configuration in place of the generation, and a note above the views says This service runs on the default configuration: every value is a default, and a gpilot.toml of your own changes them. With nothing live, the section shows the defaults the service’s last deployment without a configuration file recorded, under Nothing is deployed yet; a service that never had one says Nothing is deployed yet and that a configuration appears once a deployment has gone live.

Effective configuration: every setting the live deployment runs with, as a tree, whether you set it or it is a default. Only what I set hides the defaults, and Filter by key narrows the tree. Each value can be copied; secrets, such as a provider’s shared secret, are shown redacted here. The stored document itself is not redacted: gpilot config get returns it as it was deployed, secrets included, to members and API keys with service:edit. Each section links to its entry in the configuration reference.

Beside origin.shield, the tree names the shield’s city and country. On a plan that includes shielding it adds A request sent to the shield counts at two points of presence, so it uses twice the request units; a background refresh through it is a request of its own. (see request units); on Glider (Free) it says the shield is inactive on the plan and turns on by itself after an upgrade.

Beside the three origin timeouts, the tree adds your plan allows up to the plan’s ceiling (see what your plan allows). The ceiling is your plan’s today, not the one the deployment was built under. A key that is accepted but that nothing reads is marked read by nothing; see the findings below.

Keys that do nothing: keys in your gpilot.toml that change nothing. There are two kinds:

  • Unknown keys. Nothing reads them. Unknown keys are ignored almost everywhere in a service configuration, so a misspelled section deploys cleanly and changes nothing. This is where that becomes visible. Check the spelling against the reference.
  • Accepted keys without an effect. The key is spelled correctly and accepted for compatibility, but has no effect. There is nothing for you to fix.

Each finding names the line in the file, linked to the gpilot.toml view.

The configuration file exactly as it was deployed, for members with service:edit (a configuration can hold a provider’s shared secret); without it the view says so and links to Values, where every setting is shown with secrets redacted. Select a line number to copy a link to that line. For a deployment without a configuration file it says so: there is no gpilot.toml to show, and every setting is at its default.