Purging API

Stellate automatically creates a custom GraphQL API, the so-called Purging API, for your service that allows you to purge your cache. Purging the cache globally takes at most 150ms.

To try the purging API, head to the "Purging API" tab on your service's dashboard.

API Endpoint

The purging API for your service is available at https://admin.stellate.co/<service-name>.

Authentication

To use the Purging API you need to create and authenticate via a Purging API Token. You can create those tokens on your service's dashboard via the Purging API Tokens section under the Settings tab.

If you have used the Purging API Playground on the dashboard, you will already see some tokens named similarly as dashboard-74asd8. This is nothing to worry about, as we automatically create tokens for you when you access the Purging API Playground.

If you use the Purging API programmatically, you will need to include the token in the stellate-token (or graphcdn-token) header. See below for an example implementation in Node.js

const fetch = require('node-fetch')

async function purgeAllPosts() {
  await fetch('https://admin.stellate.co/little-frog', {
    // Always use POST for purge mutations
    method: 'POST',
    headers: {
      // and specify the Content-Type
      'Content-Type': 'application/json',
      'stellate-token': 'das09dja09sjda0s9ja...',
    },
    body: JSON.stringify({ query: `mutation { purgePost }` }),
  })
}

purgeAllPosts().catch((e) => console.error(e))

Soft purging

By default, any data you purge via the Purging API is removed from the cache immediately. If you would like to mark the data as stale and have your stale-while-revalidate (or swr) rules kick in, you can instead soft purge those documents.

To do so, pass the soft: true argument to any of the available mutations.

mutation {
  purgeUser(id: [5], soft: true)
}

Schemaless Mutations

The Purging API provides some mutations by default. Those are available for you to use whether you synced your schema with Stellate or not. If you sync your schema with Stellate, we also offer a set of custom-built mutations based on your schema, which simplifies the integration a bit.

Purge a specific type

If you want to purge an arbitrary type, optionally limited by specific key fields you can pass it in as an argument.

type Mutation {
  _purgeType(type: String!, keyFields: [KeyFieldInput!], soft: Boolean): Boolean
}

input KeyFieldInput {
  name: String!
  value: String!
}

For example to either purge all Todos, or to purge Todos identified by the key field id with value 42 run the following mutations:

# purge all cached documents containing Todo's
mutation {
	_purgeType(type: "Todo")
}

# purge specific instances
mutation {
	_purgeType(type: "Todo", keyFields: [{name: "id", value: "42"}]
}

Purge via an operation name

With this mutation, you can purge all cached results of the query with the operation name(s) you provide.

type Mutation {
  _purgeOperationName(names: [String!]!, soft: Boolean): Boolean
}

For example, to invalidate all results of queries named listUsers and listTodos[:

mutation {
  _purgeOperationName(names: ["listUsers", "listTodos"])
}

Purge query root fields by name

Purge all queries containing a specific field at the root level.

Note: there is s similarly named _purgeQueryField mutation, which extends the use of this mutation. While _purgeQuery will purge results whether or not arguments were passed in the original query, _purgeQueryField allows you to filter which documents will get purged based on those arguments.

type Mutation {
  _purgeQuery(queries: [String!]!, soft: Boolean): Boolean
}

Example:

mutation {
  _purgeQuery(queries: ["package"])
}

Purge query root fields by name and argument

type Mutation {
  _purgeQueryField(fields: [QueryFieldInput!]!, soft: Boolean): Boolean
}

input QueryFieldInput {
  name: String!
  args: _ArgumentsJSONObject
}

scalar _ArgumentsJSONObject

This is similar to the _purgeQuery mutation, however it 1) allows you to specify filters for which documents to purge based on arguments passed in the original query and 2) allows you to also purge queries where no arguments where passed.

For example, if you have the following query asking for a specific package

{
  package(name: "@urql/core") {
    __typname
    name
  }
}

you could then purge that result via the following mutation

mutation {
  _purgeQueryField(fields: [{ name: "package", args: { name: "@urql/core" } }])
}

If you wanted to only purge results from the cache where no argument was passed, you could use the following mutation. This would not remove the result cached by our earlier sample query.

mutation {
  _purgeQueryField(fields: [{ name: "package" }])
}

Purge the cache for a scope

You can purge the cache for regular scopes as well as JWT-Scopes every time we encounter a scope we'll create a surrogate key for it.

For regular scopes what we need from you is the following:

  1. The name of the scope and the arguments for that scope
  2. The arguments here are the names of the header/cookie along with its value.

The following example will purge the AUTHENTICATED scope where we saw a value of "bearer x" for the authorization header and a value of en-us for the locale header.

Config:

const stellate = {
  config: {
    scopes: { AUTHENTICATED: 'header:authorization|header:locale' }
  }
}

Purge:

mutation {
  _purgeScope(scopeName: "AUTHENTICATED", scopeArguments: [{ name: "authorization", value: "bearer x" }, { name: "locale", value: "en-us" }])
}

For a JWT-based scope all we need from you is the name of the scope alongside the value of the claim that you want to purge. Here we'll purge the cache for the JWT-Scope where we derived "Tom" as a value for the targeted attribute.

Config:

const stellate = {
  config: {
    scopes: {
      AUTHENTICATED: {
        definition: 'header:authorization',
        jwt: {
          claim: 'sub',
          algorithm: 'HS256',
          secret: ':a_very_secret_passphrase',
        },
      },
    }
  }
}
mutation {
  _purgeJwtScope(scopeName: "AUTHENTICATED", scopeValue: "Tom")
}

Purge the complete cache

You can purge all cached results Stellate has stored with the special _purgeAll mutation. Be extra careful when using this, as it will cause a traffic spike to your origin server.

mutation {
  _purgeAll
}

Additional Mutations Available with Schema Sync Enabled

Once you sync your schema with Stellate, additional mutations based on your schema will be available via the Purging API as well.

Purging Specific Types

In addition to the _purgeType mutation, you will also see more specific mutations to purge cached documents containing specific types.

type Mutation {
	purge$Type(
		id: [String!],
		soft: Boolean
	): Boolean
}

If your schema has a Package type, for example, you could run the following mutation to purge all documents containing it:

mutation {
  purgePackage
}

or this mutation to purge documents containing a specific package (assuming name was defined as a key field)

mutation {
  purgePackage(name: "@urql/core")
}

Purging Specific Query Root Fields

Similar to types, we generate more specific mutations for known query root fields.

type Mutation {
	purgeQuery_$Field(
		args: [_ArgumentsJSONObject]!,
		soft: Boolean
	): Boolean
}

scalar _ArgumentsJSONObject

Using our package example from earlier, you could rewrite that mutation as follows, as long as Stellate knows about your schema:

mutation {
  purgeQuery_package(args: { name: "@urql/core" })
}

Additional API Changes with Schema Sync Enabled

_purgeQuery and _purgeQueryField make use of a new _QueryEnum, which is built based on all the possible field names on the Query root type. Their definition changes as follows:

type Mutation {
  _purgeQuery(queries: [_QueryEnum!]!, soft: Boolean): Boolean

  _purgeQueryField(fields: [QueryFieldInput!]!, soft: Boolean): Boolean
}

input QueryFieldInput {
  name: _QueryEnum!
  args: _ArgumentsJSONObject
}

scalar _ArgumentsJSONObject

# All possible field names on the Query root type
enum _QueryEnum {
  package
}

Which requires us to also update our sample purging mutations as follows:

mutation {
  _purgeQuery(queries: [package])
}

mutation {
  _purgeQueryField(fields: [{ name: package, args: { name: "@urql/core" } }])
}