How to achieve collective quota for multiple API Products

Hi,

Suppose that all my APIs are partitioned in n API products: AP1, …,APn.

A tenant/customer (with multiple developers with multiple Dev Apps) get all API products with some Quota.

Can one have Quota for a tenant across all APx API products? I.e., can we measure that a tenant cannot have more than say 100,000 calls (of any of the API products) per day?

From the doc, it seems that each API product can have a quota that can be referenced in a quota policy. If yes, how will the quota policy look like?

1 3 731
3 REPLIES 3

The quota policy in Apigee Edge is quite flexible. One way to configure it is to tell the quota policy to use the quota limits defined in the API Product metadata. The quota policy configuration for this (after a VerifyApiKey) looks like this:

<Quota name='Quota-1'>
  <Identifier ref='request.queryparam.apikey' />
  <Allow countRef='verifyapikey.VerifyAPIKey-1.apiproduct.developer.quota.limit'/>
  <Interval ref='verifyapikey.VerifyAPIKey-1.apiproduct.developer.quota.interval'/>
  <TimeUnit ref='verifyapikey.VerifyAPIKey-1.apiproduct.developer.quota.timeunit'/>
  <Distributed>true</Distributed>
  <Synchronous>false</Synchronous>
  <PreciseAtSecondsLevel>false</PreciseAtSecondsLevel>
</Quota>

What's going on here: the Quota policy is referencing context variables that contain the settings for the Quota. Those variables get set implicitly when VerifyApiKey is executed. The VerifyApiKey policy sets them according to the metadata configured in the API Product, for which the APIKey is valid.

Now, how can you enforce a quota across API Proxies? There are a couple ways.

  1. Configure your API Products to wrap more than one API proxy. If you need to enforce quota in aggregate for calls across apiproxy1, apiproxy2, ...apiproxyN, then define an API Product that includes all of those proxies. Enable the developer app on that ONE API Product. Set the quota limit in the API Product, and configure the quota policy as above. This is the standard pattern in Apigee Edge, and it differs from what you have done, I think. Today you have a 1:1 mapping between API Product and API Proxy. This is not necessary. There is a M:N relationship between API Products and API Proxies. One product may wrap multiple proxies, and the quota for that product would apply to any call on any of the wrapped proxies.

  2. Keep the 1:1 mapping of proxy to product. Then enable a single developer app with access to multiple products. Configure the quota limits on the developer app entity. Every entity in Apigee Edge can have custom attributes attached to it. You can define custom attributes with names like "quotalimit" and "quotainterval" and so on, and then retrieve and use those attributes at runtime, and apply them in the quota policy. The configuration might look like this:

    <Quota name='Quota-1'>
      <Identifier ref='request.queryparam.apikey' />
      <Allow countRef='developer.app.quotalimit'/>
      <Interval ref='developer.app.quotainterval'/>
      <TimeUnit>month</TimeUnit> <!-- hardcoded, just for fun -->
      <Distributed>true</Distributed>
      <Synchronous>false</Synchronous>
      <PreciseAtSecondsLevel>false</PreciseAtSecondsLevel>
    </Quota>
    	

    This would allow you to keep the 1:1 APIProduct-to-APIProxy mapping you have today.The variables like "developer.app.quotalimit" and "developer.app.quotainterval" are implicitly retrieved and populated by the VerifyApiKey policy that must execute before this quota policy.

By the way, it is possible to enforce multiple quotas within an API Proxy. One of them might enforce a limit on a particular API Product, and the other might enforce a limit on the Developer App. For example, suppose you have a developer app that is authorized to use 3 different products. The quota on each product might be 25,000 requests per month. The overall quota might be 60,000 requests per month. So an app would be ok using 24,000 requests on each of the first two products, but then the app would have only 12,000 requests remaining for the final product. If any of the limits is exceeded, then the request would be rejected. You could do this by configuring 2 Quota policies in succession, with different configurations, referring to different context variables.

Another "by the way" - in the case of API key rotation, you may wish to enforce a quota on the developer app, not on the API key itself. For example, suppose you have keys that expire every 6 months, and you do not wish the use of a new API key in the middle of a month to allow the app to use more than 1 month's worth of API calls. In this case you can configure the quota to reference the developer app id, which remains constant even when you rotate API keys. Eg,

<Quota name='Quota-1'>
  <Identifier ref='developer.app.id' />
   ...

Thanks @Dino

I understand which you have mentioned in points 1 and 2.

But our case is little different. Suppose we have 5 API Products (p1,p2..p5) each having multiple API Proxies. Now the tenant (t1) can have multiple Dev Apps (d1, d2,d3) each having some combination of API Products say d1 have p1,p2,p3 and d2 have p4,p5 and so on.

Now for a tenant (t1) , I want to measure the combined quota of all the Dev apps(d1,d2,d3) and that should not exceed some threshold say 100000 calls per day.

I hope it clarifies our use case.

How we can achieve this using Quota Policy or some other mechanism ?


You can use the same approach as I described above, except: rather than attaching quota limits to the developer app, attach quota limit information to the developer entity in Edge. Just as with the developer app, it is possible to attach custom attributes to a developer.

Then, your quota policy will do something like this:

<Quota name='Quota-1'>
  <Identifier ref='developer.id' />
  <Allow countRef='my_custom_quotalimit'/>
  <Interval>1</Interval>
  <TimeUnit>day</TimeUnit> <!-- hardcoded, just for fun -->
  <Distributed>true</Distributed>
  <Synchronous>false</Synchronous>
  <PreciseAtSecondsLevel>false</PreciseAtSecondsLevel>
</Quota> 

One key difference - we use the developer.id for the Identifier. This means the quota applies to all instances of all apps attached to that developer. (And all products, etc).

There is one additional difference here. VerifyApiKey will not automatically and implicitly retrieve the attributes for the developer, and set appropriate context variables. For attributes attached to the app, VAK does this automatically. For attributes attached to the developer, you must configure your proxy to do that explicitly.

To do so, after VerifyApiKey, insert a policy called AccessEntity, which will use the developer.id set by VerifyApiKey, to retrieve all the attributes associated to the developer. Then use ExtractVariables to get the attribute that specifies the quota limit, and the interval (if you want). Usually the interval is 1. Eg, 100,000 requests per 1 day. So it may be that you want only the 100,000 number.

ExtractVariables will set the context variable that contains the 100,000 number (or whatever it is). In the above example this is my_custom_quotalimit.

So the ordering of policies is:

  • VerifyApiKey (or OAuthV2/VerifyAccessToken)
  • AccessEntity - for the developer
  • ExtractVariables - to get the value from the developer
  • Quota

This is something I'd want to put into a shared flow so that the same logic could be re-used across all those API Proxies.