Rate Limiting in GraphQL
Introduction
In this lesson, we'll focus on securing your GraphQL API by implementing rate limiting. As we secure our APIs, it's crucial to prevent abuse, and rate limiting is a powerful tool for this purpose. Rate limiting helps manage the number of requests a user can make to your API within a specific time frame, ensuring it can handle heavy loads gracefully.
We'll use the rack-attack gem in this lesson. This gem is popular for rate limiting in Rack-based applications (including Sinatra) due to its simplicity and flexibility.
By the end of this lesson, you'll be equipped to add rate limiting to your GraphQL API, protecting your resources and improving the performance and reliability of your server.
Defining the GraphQL Schema
The schema defines the structure of the data and the queries that can be made. We'll define a simple schema for our books example using graphql-ruby's class-based approach:
Here's a brief explanation:
BookType: Defines a book type with fieldsid,title, andauthor, all of which are non-nullable.QueryType: Defines a query to fetch a list of books with a resolver method that returns sample data.AppSchema: The main schema class that ties everything together.
Implementing Rate Limiting in Sinatra
Now, let's introduce rate limiting to our Sinatra application using Rack middleware. We'll use the rack-attack gem for this. Here's how to set it up:
First, require the necessary libraries:
Next, configure Rack::Attack with rate limiting settings:
Here's a breakdown of this code:
cache.store: Sets up an in-memory store for tracking requests (you can use Redis in production).throttle: Defines the rate limit rule —100requests per15minutes per IP address.req.ip: The discriminator that identifies unique clients (by IP address).throttled_responder: Custom response when the rate limit is exceeded (429status code).
To apply rate limiting to specific endpoints only, you can add conditions within the throttle block, such as checking req.path.
Integrating graphql-ruby with Sinatra
Next, we need to set up our GraphQL endpoint in Sinatra. We'll create a POST route that handles GraphQL queries:
In this setup:
- We parse the incoming JSON request body to extract the GraphQL query and variables.
AppSchema.execute: Executes the GraphQL query against our schema.- The result is converted to JSON and returned to the client.
Finally, start the Sinatra server:
Testing the Implementation
To test our implementation, we'll query the GraphQL API to see if rate limiting is working as intended. Here's a Ruby script using net/http to send 105 requests — just enough to exceed the limit of 100 requests per 15 minutes and trigger the 429 Too Many Requests response:
The first 100 requests should succeed with a 200 status code, returning the list of books. After that, the remaining requests should be rejected with a 429 Too Many Requests response. Here's what the output looks like:
The summary at the end confirms that exactly 100 requests were allowed through and the remaining 5 were blocked by our rate limiter.
Lesson Summary
In this lesson, we covered:
- Defining a simple GraphQL schema using
graphql-ruby's class-based approach. - Applying rate limiting middleware to a Sinatra app using
Rack::Attack. - Integrating
graphql-rubywith Sinatra to secure GraphQL APIs. - Testing the implementation to observe rate limiting in action.
By applying these techniques, you ensure your GraphQL API is more secure and can handle high loads in a stable manner. Well done on reaching the end of this lesson! Now it's time to put your knowledge into practice with the exercises that follow. Keep exploring and refining your skills in GraphQL and API security.
