How to Rate Limit GraphQL API: Simple Guide and Example
To rate limit a
GraphQL API, use middleware that tracks request counts per user or IP and blocks requests exceeding a set limit. Common tools include express-rate-limit for Node.js servers, applied before the GraphQL handler to control query frequency and prevent abuse.Syntax
Rate limiting in GraphQL is usually done by adding middleware before the GraphQL server processes requests. The middleware checks how many requests a client has made in a time window and blocks excess requests.
Key parts:
windowMs: Time frame for counting requests (e.g., 15 minutes).max: Maximum allowed requests in that time.keyGenerator: Function to identify clients (by IP or user ID).handler: Function called when limit is exceeded.
javascript
const rateLimit = require('express-rate-limit'); const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // limit each IP to 100 requests per windowMs keyGenerator: (req) => req.ip, // identify client by IP handler: (req, res) => { res.status(429).json({ error: 'Too many requests, please try again later.' }); } }); app.use('/graphql', limiter, graphqlHTTP({ schema }));
Example
This example shows how to add rate limiting to a GraphQL API using express-rate-limit with an Express server. It limits each IP to 5 requests per minute and returns an error if exceeded.
javascript
const express = require('express'); const { graphqlHTTP } = require('express-graphql'); const { buildSchema } = require('graphql'); const rateLimit = require('express-rate-limit'); // Define a simple schema const schema = buildSchema(` type Query { hello: String } `); // Root resolver const root = { hello: () => 'Hello world!' }; const app = express(); // Rate limiter middleware const limiter = rateLimit({ windowMs: 60 * 1000, // 1 minute max: 5, // limit each IP to 5 requests per windowMs handler: (req, res) => { res.status(429).json({ error: 'Too many requests, slow down!' }); } }); // Apply rate limiter to /graphql endpoint app.use('/graphql', limiter, graphqlHTTP({ schema: schema, rootValue: root, graphiql: true })); app.listen(4000, () => { console.log('Running a GraphQL API server at http://localhost:4000/graphql'); });
Output
Running a GraphQL API server at http://localhost:4000/graphql
Common Pitfalls
- Not applying rate limiting middleware before the GraphQL handler: This causes unlimited requests to reach your API.
- Using IP only for key generation in shared networks: This can block many users behind the same IP.
- Setting limits too low or too high: Too low frustrates users; too high fails to protect the server.
- Ignoring authentication: For authenticated APIs, use user ID instead of IP to track limits.
javascript
/* Wrong: Applying limiter after GraphQL handler (ineffective) */ app.use('/graphql', graphqlHTTP({ schema }), limiter); /* Right: Apply limiter before GraphQL handler */ app.use('/graphql', limiter, graphqlHTTP({ schema }));
Quick Reference
Tips for effective GraphQL rate limiting:
- Use middleware like
express-rate-limitbefore your GraphQL server. - Identify clients by IP or user ID depending on your app.
- Set reasonable
maxandwindowMsvalues based on expected traffic. - Return clear error messages with HTTP 429 status when limits are exceeded.
- Consider more advanced solutions like Redis stores for distributed rate limiting.
Key Takeaways
Apply rate limiting middleware before the GraphQL handler to control request flow.
Use client identifiers like IP or user ID to track request counts accurately.
Set limits that balance user experience and server protection.
Return HTTP 429 status with a clear message when limits are exceeded.
Consider distributed stores like Redis for scalable rate limiting.