Throttling


Opening an API to the public means many things can go wrong, some users might abuse it and some will play trial and error. Given the dynamic nature of graphQL, users are responsible for making the queries, and intentionally or not they can come up with extremely expensive queries. In order to prevent those from happening and affecting the entire performance of the API, some measures have to be taken. That's why we have implemented a rate-limiting based on user quotas.

Each operation performed by the public API has a calculated complexity, representing the cost of executing that particular operation. Following this, users are given an amount of credits to be used within a period of time (usually one hour). How many operations you can execute will depend on how you build them. The same query can have a different complexity if you decide to fetch a lot of information from the results, or if you navigate across relationships to enrich the results.

Given the dynamic nature of graphQL operations it might be hard to imagine the cost of an operation, so here's where the analyze parameter available in queries becomes relevant. If you send analyze: true the query won't be executed, but instead, only the complexity will be calculated. You can then retrieve the cost of that query by accessing the complexity field from the response.

Analyzing query
 query { 
    products(analyze: true) { 
        complexity 
        request_id 
        data(first: 10) { 
            edges { 
                node { 
                    id 
                    sku 
                    name 
                    warehouse_products { 
                        id 
                        warehouse_id 
                        on_hand
                    }
                }
            }
        }
    }
}

In this case, the result won't include any products, the query won't be executed, it will only be analyzed to calculate its complexity, giving the user the possibility to know beforehand how many credits it will consume.

The output would look like this:

{
    "data": {
        "products": {
            "complexity": 101,
            "request_id": "5cea345gsn87a",
            "data": {
                "edges": []
            }
        }
    }
}
Throttling error

When you request an operation that exceeds your user quota you will receive an error like this one:

 {
    "errors": [
        {
            "message": "There are not enough credits to perform the requested operation, which requires 101 credits, but there are only 50 credits left. You can execute queries up to that level or wait 60 minutes until your quota is refreshed.",
            "operation": "products",
            "request_id": "5cea345gsn87a",
            "required_credits": 101,
            "remaining_credits": 50,
            "time_remaining": "60 minutes"
        }
    ],
    "data": {
        "products": null
    }
}

User Quota

After a few operations, you might want to know how many credits you have available and for how long. That's exactly what the user_quota query will provide you:

query { 
    user_quota { 
        is_expired 
        expiration_date 
        time_remaining 
        credits_remaining
    }
}

Next steps