⚡️ Pro Feature ⚡️ This feature is bundled with GraphQL-Pro.

Getting Started

To use GraphQL::Pro::OperationStore with your app, follow these steps:


OperationStore requires two gems in your application environment:

These are bundled with Rails by default.

Prepare the Database

If you’re going to store data with ActiveRecord, migrate the database to prepare tables for it.

Add OperationStore

To hook up the storage to your schema, add the plugin:

class MySchema < GraphQL::Schema
  # Add it _after_ other tracing-related features, for example:
  # use GraphQL::Tracing::DataDogTracing
  # ...
  use GraphQL::Pro::OperationStore

Make sure to add this feature after other Tracing-based features so that those other features will have access to the loaded query string. Otherwise, you may get "No query string was present" errors.

By default, it uses ActiveRecord. It also accepts:

Also, you can disable updates to “last used at” with default_touch_last_used_at: false. (This can also be configured per-query with context[:operation_store_touch_last_used_at] = true|false.)

Add Routes

To use OperationStore, add two routes to your app:

# config/routes.rb

# Include GraphQL::Pro's routing extensions:
using GraphQL::Pro::Routes

Rails.application.routes.draw do
  # ...
  # Add the Dashboard
  # TODO: authorize, see the dashboard guide
  mount MySchema.dashboard, at: "/graphql/dashboard"
  # Add the Sync API (authorization built-in)
  mount MySchema.operation_store_sync, at: "/graphql/sync"

MySchema.operation_store_sync receives pushes from clients. See Client Workflow for more info on how this endpoint is used.

MySchema.dashboard includes a web view to the OperationStore, visible at /graphql/dashboard. See the Dashboard guide for more details, including authorization.

GraphQL Persisted Operations Dashboard

operation_store_sync and dashboard are both Rack apps, so you can mount them in Rails, Sinatra, or any other Rack app.

Alternatively, you can configure the routes to load your schema lazily, during the first request:

# Provide the fully-qualified class name of your schema:
lazy_routes = GraphQL::Pro::Routes::Lazy.new("MySchema")
mount lazy_routes.dashboard, at: "/graphql/dashboard"
mount lazy_routes.operation_store_sync, at: "/graphql/sync"

Update the Controller

Add operation_id: to your GraphQL context:

# app/controllers/graphql_controller.rb
context = {
  # Relay / Apollo 1.x:
  operation_id: params[:operationId]
  # Or, Apollo Link:
  # operation_id: params[:extensions][:operationId]

  # ...
  context: context,

OperationStore will use operation_id to fetch the operation from the database.

See Server Management for details about rejecting GraphQL from params[:query].

Next Steps

Sync your operations with the Client Workflow.