What's the logic behind quota_renews?


#1

Hi,

The docs is a bit confusing for me about quota renewals. Please help me understand how to use it correctly.

I have a simple scenario: users pay monthly (or yearly) to get access to our API. If the user pays the next month, we extend the permissions for the next month, if not then we either block the access completely or give a fallback access. I’m considering to use organizations’ quota_renews or key’s expires to set to control a user’s access to our API. I go in to details about my question below.

Trying to figure out what to set exactly in the normal flow of a user. I have to approaches and I don’t know which works, or which one is the better.

approach A:

  1. The user signs up:
    we create an organization for them
    we also create an initial key for the user with no quota (quota_max = -1) and no expiry (expires = -1)
  2. The user buys a monthly license for the first time, so we set the following
    user’s organization’s quota_remaining to the maximum enabled in the limit
    user’s organization’s quota_renews to the end of the monthly period, <- this sets the end of period
    user’s organization’s quota_max to the fallback enabled transactions for the case the user wouldn’t pay the monthly fee
    user’s organization’s quota_renewal_rate to the period length how often we’d renew the fallback transaction amount for the case the user still hasn’t paid the monthly fee. (Is this required? What if we don’t want the quota to renew?)
    the user’s all keys’ allowance and rate to the performance throttling enabled in the license
  3. When the user pays the next month, we set the organization’s quota_remaining and quota_renews.

approach B:

  1. The user signs up (this is the same):
    - we create an organization for them
    - we also create an initial key for the user with no quota (quota_max = -1) and no expiry (expires = -1)
  2. The user buys a monthly license for the first time, so we set the
    - user’s organization’s quota_remaining to the maximum enabled in the limit
    - user’s all keys’ expires to the end of the actual monthly period, <- this sets the end of period
    (setting user’s organization’s quota_max, quota_renews and quota_renewal_rate doesn’t really make sense in this case)
  3. When the user pays the next month, we set the
    - user’s organization’s quota_remaining to the new maximum.
    - user’s all keys’ expires to the end of the new actual monthly period.

So my question is which one is the preferred way, or is there something I get wrong about quotas?

Thanks,
Gergely


#2
  1. Why are you creating an organisation for each user? Organisations are a mechanism to organise APIs and user ownership (tenants), not a structure to group API tokens, you’ll get very odd behaviour if you go down this route since Orgs Own tokens and crossover is hard.

  2. You can set quotas on individual tokens. The quota renewal is actually automatically set, the way it works is like this:

  • Request comes in
  • Tyk reduces the quota for the user (quota remaining)
  • If the quota reaches 0 and the quota renewal date is in the future, block the request - as they still have a while to go until it renews
  • if the quota reaches 0 and the renewal date is in the past, then Tyk will reset the quota_remaining to the max and also re-set the quote renewal time stamp to the period that has been specified in quota renewal rate, e.g. Another 30 days

So you can do two things:

  • set a hard quota with a renewal date at the end of the month, and let Tyk handle the periodicity, you can use the events system to kick off an activity that warns you if they hit their quota
  • manually manage the quota

I’m not sure you need to synchronise the token expiry and quotas, it seems overkill. Tyk’s built-in quota should work just fine here unless you really really need a monthly re-set, in which case you can use any mechanism you like - Tyk will always renew the quota if it can, it’s built that way. So you’d need to externalise it somehow or set the max to 0 so when it does try to renew it just zeroes it.

When a quota is hit, you need to reset the quota on the token to release the lock (there’s a parameter for that). Now if you were manually handling that you could just zero out the renewal, hook into an event handler to set some kind of timed reset call.

Also, and this might be more practically speaking, expiring a token to enforce the quota defeats the purpose of the quota, an expiry should just be the maximum lifetime of the token (so you don’t have tokens floating around granting access forever), expiry errors also imply token renewal, which isn’t happening here.

The built in quota can be reset and managed quite easily, and it won’t cause a developer to worry about having to renew the token in their app (even if you are extending the expiry), it’s more semantically correct.

Not sure how helpful this all is, but you have quite a few options.

M.


#3

Thank you for the explanation, this makes things much more clear!

I thought about having organizations, to enable users having multiple keys (like one for their developers, one for production), but all having the same quota together. This is a nice-to-have feature for us, so if you say it makes things significantly more complicated, then I’d go on with the key-only approach, as you recommend.

My best solution so far is to have some days after the end of the payed period when we try to make the new payment. Let’s call this the payment_tolerance (a time period eg 5 days). This case:

When the user pays the first monthly fee, we set:

  • quota_max = the fallback value for no payment (eg daily 1000)
  • quota_remaining = as defined in the license
  • quota_renews = the end date of the paid period + payment_tolerance
  • quota_renewal_rate = the length of the fallback period (eg 1 day)

We manually watch dates and after the end of the actual period (but without the payment_tolerance time added), we try to make the payment. Only if it’s successful, we set:

  • quota_remaining = as defined in the license
  • quota_renews = the end date of the paid period + payment_tolerance

This seems to be the simplest way for me so far.

I tried to figure out a logic without the payment_tolerance time too, but it’s not simpler a bit:

  • This case we have to make the payment before the end of the period, and if it’s successful then set the quota_max match the payed license and quota_renews to match to the beginning of the payed period. But there’s a problem with this: if the user doesn’t use all the quota in the first month, this solution enables them to use up to a 2 monthly quota in the second month.

  • This problem is even more interesting if the new payment for a second month wasn’t successful: this case it’s possible that the user pays one month, but not the second, but only use the quotas in the second month, and not in the first.

To avoid this we need to watch dates manually and force to reset quota_remaining manually, and at this point this solution already seems even more complex. If there would be an option to automatically reset the quota_remaining at the quota_renews date by tyk, it would solve the problem, but it’s not how you described the system.

Gergely


#4

I think it’s completely overcomplicated.

If a payment fails, why not just set the is_inactive flag to true? This will instantly deny access, regardless of the quota status and renewal. Once they’ve paid you can reset the quota if necessary?