DOCS

GraphQL API Rate Limiting

GraphQL API rate limiting

Learn how Zonos calculates query costs based on complexity.

Zonos rate limits GraphQL API requests based on query complexity rather than request count. This ensures fair usage while allowing you to request exactly the data you need.

Why complexity-based rate limiting? 

Traditional REST APIs use request-based rate limiting where every request consumes the same credits, whether you fetch one field or hundreds, and whether you read or modify data—despite the significant difference in server load.

GraphQL's query complexity-based approach solves this by calculating costs based on the actual data requested and operations performed. This gives you more flexibility to request what you need while providing predictable server load.

Rate limit 

Zonos uses a point-based system where each query deducts points based on its complexity. You have a pool of available points that:

  • Refills at 3,000 points per second (30,000 points per 10 seconds)
  • Has a maximum capacity of 300,000 points

This allows you to make occasional bursts of complex queries while maintaining a sustainable request pace.

How query cost is calculated 

Every GraphQL request has a cost calculated before execution:

Base costs

  • Query: 5 points
  • Mutation: 10 points
  • Object: 1 point per object returned
  • Scalar fields: 0 points (free)

Scalar fields like strings, integers, IDs, and booleans don't add to the cost. You only pay for the base operation and the objects returned.

Example: Simple query

1query {
2 landedCost(id: "123") {
3 id
4 createdBy
5 shipToCountry
6 }
7}

Cost breakdown: 5 (base query) + 1 (landed cost object) = 6 points

The scalar fields (id, name, currency) are free.

Example: Query with multiple objects

1{
2 orders(first: 10, filter: { status: COMPLETED }) {
3 edges {
4 cursor
5 node {
6 id
7 }
8 }
9 }
10}

Cost breakdown: 5 (base query) + 10 (10 orders × 1 point each) = 15 points

Example: Mutation

1mutation {
2 landedCostCalculate(input: { ... }) {
3 id
4 }
5}

Cost breakdown: 10 (base mutation) + approximately 50 (objects returned) = 60 points

A typical landed cost calculation costs around 60 points in complexity.

Viewing query complexity 

Every API response includes a zonos-query-complexity header showing your query's cost:

1zonos-query-complexity: 58

This header tells you exactly how many points the query consumed. Use it to monitor your API usage and optimize expensive queries.

Handling rate limits 

If you exceed your rate limit, you'll receive an error message. To handle rate limits effectively:

Monitor your complexity

Check the zonos-query-complexity header in responses to understand your query costs and identify expensive patterns.

Implement retry logic

If you hit rate limits, implement exponential backoff and retry logic. Since the bucket refills at 3,000 points per second, calculate appropriate wait times based on your query complexity.

Batch efficiently

GraphQL allows you to request multiple queries in a single request:

1{
2 landedCost(id: "landed_cost_123") {
3 id
4 createdAt
5 }
6 order(orderId: "order_123") {
7 id
8 status
9 createdAt
10 }
11}

Best practices 

Request only what you need

Query complexity is proportional to the data you request. Structure your queries to fetch only the fields and objects you'll actually use.

1query {
2 order(orderId: "order_123") {
3 id
4 status
5 createdAt
6 updatedAt
7 items {
8 id
9 name
10 quantity
11 amount
12 }
13 shipments {
14 id
15 }
16 }
17}

Paginate large datasets

When requesting multiple objects, use reasonable page sizes:

1{
2 orders(first: 100, filter: { status: COMPLETED }) {
3 edges {
4 cursor
5 node {
6 id
7 }
8 }
9 }
10}

Request 10-50 items at a time and paginate through results as needed, rather than requesting hundreds of objects in a single query.

Avoid unnecessary nesting

Each nested object adds to your complexity. Only request nested data when you actually need it.

Book a demo

Was this page helpful?