Enforcing quota per app

We are wanting to enforce an API quota per app. I am reading the documentation on the Identifier element for the quota policy, and it states that using the developer.app.id variable is not recommended. If we shouldn't use that variable, what should we use to identify an application?

I had submitted a feature request for this last year, and the interim workaround/suggestion (until a more stable ID could be provided) was to use a combination of the developer email and application name, since this is how the REST API identifies an application.

Is there a way we can reference multiple flow variables in the Identifier element to achieve this? Or do we have to generate a new flow variable ourselves (e.g. using a JS callout) to concatenate the app name and developer email? I'd like to avoid doing this, since it adds extra request latency.

I'm happy to reference existing documentation on this subject if any already exists. Any examples and/or suggestions are much appreciated, thanks!

Solved Solved
0 3 235
1 ACCEPTED SOLUTION

I never understood the recommendation to not use the developer.app.id as the Quota identifier.

The stated reason for recommending against using it is, the developer.app.id may change. My understanding is that the app id might change during database migration, or during an upgrade from Apigee Edge to Apigee X. Those changes, to me, won't typically affect how a quota works. I presume the quota will have a time window, like an hour or a day or maybe even a month. The developer.app.id, if it changes, would change once in a long, long while. So you will have many hours or days or months during which the developer.app.id is completely stable. There may be a moment during which the app.id changes, in which case your quota won't be strictly enforced during the time window in which the change occurred. But that would be a one-time event, and it would affect only the single time window (hour or day etc) for which the quota gets applied.

I think it's a bad recommendation. I'd advise you to use it and be aware that in some distant future, you may have a missed quota count, once. If that's not tolerable, then you will need to find a more stable ID. One way to do that is attach a custom attribute to the developer app that YOU define. a uuid or guid. You can be assured that the value will remain stable even in the face of database migrations. Your idea of using a compound identifier that uses developer email and app name would also work.

Is there a way we can reference multiple flow variables in the Identifier element to achieve this? Or do we have to generate a new flow variable ourselves (e.g. using a JS callout) to concatenate the app name and developer email? I'd like to avoid doing this, since it adds extra request latency.

No, there is no direct way to do that. The best way to assign a variable from two other variables, to produce that compound identifier, is to use AssignMessage:

 

<AssignMessage name='AM-QuotaIdentifier'>
  <AssignVariable>
    <Name>my-identifier</Name>
    <Template>{developer.email}-{developer.app.name}</Template>
  </AssignVariable> 
</AssignMessage>

 

The AssignMessage itself will be quite speedy, won't add appreciable latency to the request handling. But, if you want to refer to the developer email, afaik, that requires a preceding AccessEntity call, which involves IO which does incur latency. 

The custom attribute on the app would not incur that latency - it would be retrieved from storage in the call to VerifyApiKey or VerifyAccessToken, and so the I/O cost would be amortized into that call, and would be implicitly cached. So that might be speedier.

View solution in original post

3 REPLIES 3

I never understood the recommendation to not use the developer.app.id as the Quota identifier.

The stated reason for recommending against using it is, the developer.app.id may change. My understanding is that the app id might change during database migration, or during an upgrade from Apigee Edge to Apigee X. Those changes, to me, won't typically affect how a quota works. I presume the quota will have a time window, like an hour or a day or maybe even a month. The developer.app.id, if it changes, would change once in a long, long while. So you will have many hours or days or months during which the developer.app.id is completely stable. There may be a moment during which the app.id changes, in which case your quota won't be strictly enforced during the time window in which the change occurred. But that would be a one-time event, and it would affect only the single time window (hour or day etc) for which the quota gets applied.

I think it's a bad recommendation. I'd advise you to use it and be aware that in some distant future, you may have a missed quota count, once. If that's not tolerable, then you will need to find a more stable ID. One way to do that is attach a custom attribute to the developer app that YOU define. a uuid or guid. You can be assured that the value will remain stable even in the face of database migrations. Your idea of using a compound identifier that uses developer email and app name would also work.

Is there a way we can reference multiple flow variables in the Identifier element to achieve this? Or do we have to generate a new flow variable ourselves (e.g. using a JS callout) to concatenate the app name and developer email? I'd like to avoid doing this, since it adds extra request latency.

No, there is no direct way to do that. The best way to assign a variable from two other variables, to produce that compound identifier, is to use AssignMessage:

 

<AssignMessage name='AM-QuotaIdentifier'>
  <AssignVariable>
    <Name>my-identifier</Name>
    <Template>{developer.email}-{developer.app.name}</Template>
  </AssignVariable> 
</AssignMessage>

 

The AssignMessage itself will be quite speedy, won't add appreciable latency to the request handling. But, if you want to refer to the developer email, afaik, that requires a preceding AccessEntity call, which involves IO which does incur latency. 

The custom attribute on the app would not incur that latency - it would be retrieved from storage in the call to VerifyApiKey or VerifyAccessToken, and so the I/O cost would be amortized into that call, and would be implicitly cached. So that might be speedier.

Thanks, and I agree with your justification for using the app.id. My quotas aren't enforced for any long period of time, so it's likely ok that the IDs themselves aren't persistent. It looks like you work for Google - is this feedback you'd be able to pass up the chain about app IDs? Mainly trying to cast a wide net to supplement the request I already submitted to support to provide a more persistent ID for apps. In this case, perhaps the overarching feedback is: Don't suggest we shouldn't do something without suggesting what we should do instead.

Yes I work for Google.  I'll do that.