Helpers

Stellate provide you with a set of functions that help you define rules for rate limiting more efficiently. Some of these functions take in the same req argument that we pass to the config functions like rateLimits and getConsumerIdentifiers, for more details on this object see the API Reference.

isQuery

Returns true if the given request is a GraphQL query, and false otherwise.

function isQuery(req: EdgeRequest): boolean

isMutation

Returns true if the given request is a GraphQL mutation, and false otherwise.

function isMutation(req: EdgeRequest): boolean

hasRootField

Returns true if the given request contains the given field name in the root selection set, and false otherwise.

function hasRootField(req: EdgeRequest, rootField: string): boolean

byField

This helper comes in handy if you want to define limits that apply to certain queries or mutations. It will return a function that generates the appropriate list of rate limit rules for the given request. All generated rules will limit by request count.

function byField(
  req: EdgeRequest,
  { queryFields, mutationFields, ...baseConfig }: ByFieldConfig,
): DynamicRateLimitRule[]

type ByFieldConfig = {
  // Defile limits for individual fields of the query root operation types
  queryFields?: FieldConfigMap
  // Defile limits for individual fields of the mutation root operation types
  mutationFields?: FieldConfigMap

  // The following properties will be shared across all generated rate limit rules
  name: string
  description?: string
  state?: 'enabled' | 'disabled' | 'dryRun'
  allowList?: readonly string[]
} & (
  | {
      groupBy:
        | 'ip'
        | { header: string }
        | { cookie: string }
        | { jwt: string }
        | { consumerIdentifier: string }
    }
  | { group: string | number }
)

type FieldConfigMap = {
  [fieldName: string]: {
    budget: number
    window: TimeWindow
  }
}

Example

import { Config } from 'stellate'
import { byField } from 'stellate/rate-limiting'

const config: Config = {
  config: {
    rateLimits: (req) =>
      byField(req, {
        name: 'Limit queries and mutations',
        state: 'enabled',
        groupBy: 'ip',
        queryFields: {
          // Generous limits for querying a list of products and individual products
          products: { budget: 10000, window: '1m' },
          product: { budget: 2000, window: '1m' },
        },
        mutationFields: {
          // Only allow adding one product to the cart each second
          addToCart: { budget: 1, window: '1s' },
        },
      }),
  },
}
export default config