API Management: advanced usage quota
Tags: azure, api
Published: 2022-07-12 09:48:23

## Introduction

>Azure API Management is a hybrid, multicloud management platform for APIs across all environments.

For more information on API Management, check out Microsoft Docs:
[About API Management](https://docs.microsoft.com/en-us/azure/api-management/api-management-key-concepts).

API Management (APIM) is an Azure service that enables you to manage APIs as first-class assets throughout their lifecycle. It consists of an API
_Gateway_, a _management plane_ and a _developer portal_. All these components are hosted in Azure and are completely managed by default.
Each component has its own place in the ecosystem:

* **API Gateway**  
  Acts as a façade to the backend services
* **Management Plane**  
  Provides full access to the API Management service capabilities
* **Developer Portal**  
  Used to discover the APIs, onboard to use them, and learn how to consume them

![Key components of Azure API Management](https://docs.microsoft.com/en-us/azure/api-management/media/api-management-key-concepts/api-management-components.png)

## Rate limits and quotas

The power of APIM is that it enables you to define different types of policies on different levels, giving you lots of power on how your
APIs are being used. For instance, you can define rate limits and quotas for your APIs. By defining and checking these in APIM, you can
control the consumption of your APIs early; requests that exceed the rate limit or quota will be rejected at APIM level and will not even
hit your backend service.

But sometimes the built-in quotas might not be enough, forcing you to define your own. For one of our customers we had the requirement to
have something like credit for two specific API operations. Customers would buy API-credit (separate from the product they subscribed to)
for a specific amount of requests. Whenever the API is called, it checks to see if the customer still has credit available. If they have,
the API is called as normal. Otherwise, the customer will get a response indicating they don't have credit and they cannot call the API
anymore, or they need to buy more credit. This last scenario should be configurable by the sales team.

Again, these credits are not connected to the product a customer subscribes to. And each customer might have different levels of credit for
the same API operation. This flexibility combined with the requested ease of configuration made it impossible to completely manage this in
APIM without building too complex code and/or policies.

## The options

Because of the expected load of the API endpoints, calling out into for instance an Azure Function to check and see if a customer still has
credit available would not be a great fit. The intial reason for this customer to move to APIM was that they were having performance issues
trying to store usage statistics to enable them to implement rate limiting.

In the end we decided to create API middleware that would allow us to check the credit status for a specific API. But it is middleware with
a smart addition...

## The solution

Since performance is key, and overshooting quota by a few requests is not an issue, the amount of requests and the customer credit can be
cached in memory for a certain amount of time. At least for now. If need be we can always move it to a distributed cache like Redis. But how
will we know the amount of requests a customer has made? This is where the
[Azure API Management REST API](https://docs.microsoft.com/en-us/rest/api/apimanagement/) comes in, and more specifically the operation
[Quota By Counter Keys - List By Service](https://docs.microsoft.com/en-us/rest/api/apimanagement/current-ga/quota-by-counter-keys/list-by-service).
This API ...

>Lists a collection of current quota counter periods associated with the counter-key configured in the policy on the specified service
instance.

This means it allows us to retrieve the _Number of times Counter was called_ and even the _Data Transferred in KiloBytes_.

```json
{
  "value": [
    {
      "counterKey": "xxx.xxx.xxx.xxx",
      "periodKey": "SOME_PERIODKEY",
      "periodStartTime": "2022-07-01T00:00:00Z",
      "periodEndTime": "2022-12-31T00:00:00Z",
      "value":
      {
        "callsCount": 42,
        "kbTransferred": 1796.5453825
      }
    }
  ],
  "count": 1,
  "nextLink": null
}
```

Combining the information from the API Management "Quota By Counter Keys" REST API and the customer credit, we can create middleware that
checks the credit against the number of requests made. Caching the information in the middleware is up to the user's discretion.