💂♀️ GraphQL Rate Limit 💂♂️
A GraphQL directive to add basic but granular rate limiting to your Queries or Mutations.
Features
- 💂♀️ Add rate limits to queries or mutations
- 🔑 Add filters to rate limits based on the query or mutation args
- ❌ Custom error messaging
- ⏰ Configure using a simple
max
per window
arguments - 💼 Custom stores, use Redis, Postgres, Mongo... it defaults to in-memory
- 💪 Written in TypeScript
Install
yarn add graphql-rate-limit
Example
directive @rateLimit(
max: Int,
window: String,
message: String,
identityArgs: [String],
) on FIELD_DEFINITION
type Query {
getItems: [Item] @rateLimit(window: "1s", max: 5)
getItem(id: ID!): Item @rateLimit(identityArgs: ["id"])
}
type Mutation {
createItem(title: String!): Item @rateLimit(message: "You are doing that too often.")
}
Usage
Step 1.
Create a configured GraphQLRateLimit class.
const { createRateLimitDirective } = require('graphql-rate-limit');
import { createRateLimitDirective } from 'graphql-rate-limit';
const GraphQLRateLimit = createRateLimitDirective({
identifyContext: (ctx) => ctx.user.id,
store: new MyCustomStore(),
formatError: ({ fieldName }) => {
return `Woah there, you are doing way too much ${fieldName}`
}
});
Step 2.
Add GraphQLRateLimit to your GraphQL server configuration. Example using Apollo Server:
const server = new ApolloServer({
typeDefs,
resolvers,
schemaDirectives: {
rateLimit: GraphQLRateLimit
}
});
Step 3.
Use in your GraphQL Schema.
directive @rateLimit(
max: Int,
window: String,
message: String,
identityArgs: [String],
) on FIELD_DEFINITION
type Query {
getThings: [Thing] @rateLimit(max: 10, window: "6s")
}
type Query {
login(email: String!, password: String!): String @rateLimit(max: 10, window: "2h", identityArgs: ["email"])
}
Note: We use Zeit's ms
to parse the window
arg, docs here.
Redis Store usage
It is recommended to use a persistent store rather than the default InMemoryStore.
GraphQLRateLimit supports Redis. You need to install Redis in your project first.
import * as graphqlRateLimit from 'graphql-rate-limit';
const GraphQLRateLimit = graphqlRateLimit.createRateLimitDirective({
identifyContext: ctx => ctx.user.id,
store: new graphqlRateLimit.RedisStore(redis.createClient())
});