API Rate Limits
API rate limits are set on /api endpoints to prevent large spikes in the number of API calls that could degrade Deep Security Manager performance.
API call rates are measured as the number of API calls that Deep Security Manager receives within the last sixty seconds. When a rate limit is exceeded, the manager does not process requests until the call rate falls below all rate limits.
When a call is made and an API rate limit is exceeded, the response code is 429
with the message Too many API requests
.
Configure API rate limits
Set rate limits that are appropriate for your Deep Security Manager environment. Your limits need to allow expected API usage while protecting against accidental or malicious over-use. You can disable the API rate limiter if desired.
Rate limits are applied to the following entities:
- User: The number of API calls that the manager can receive from an API key per minute.
- Tenant: The number of calls that a tenant (including the primary tenant) can receive per minute. This limit effectively sets a collective limit on all API keys that have been created on a tenant. For example, if users are limited to 300 calls per minute and tenants are limited to 1000 calls per minute, the total calls from 4 API keys could reach the tenant limit without exceeding the user limit.
- Manager node: The number of calls a manager node can receive per minute. This limit effectively sets a collective limit on calls made to all tenants on a single instance of Deep Security Manager. Multiple tenants can collectively exceed their node's rate limit without any of them having exceeded the tenant limit.
The limits apply to each user, tenant, and node. You cannot set a different limit for an individual entity.
Determine suitable rate limits
The rate limits that you use for your Deep Security Manager instances depend on the available resources of your manager computer and the API traffic that they receive. The following rate limits are set by default:
- User: 500
- Tenant: 1000
- Node: 5000
To determine whether your current rate limits are suitable for your environment, observe the behavior of your scripts and the computer of the manager instance that they are calling:
- Raise the limits if your scripts often exceed the limits and manager resources are not highly impacted.
- Lower the limits if you observe periods of high resource usage on the manager computer when spikes in API calls occur.
You can use the APIUsageAPI
class of an SDK to determine call rates. (See API Usage in the API Reference.) For example you can search for all API calls that occur during a certain time period. Parse the returned data to count the total calls. You can also find the number of code 429 responses. (See Date-range searches.)
Set the rate limits
Use the dsm_c
command of the Deep Security Manager CLI to set rate limits. You can also disable and enable the rate limiter. When disabled, rate limiting is not enforced and the rate limits that are set are not effective.
The following table lists the setting names that you can use with the changesetting
and viewsetting
actions of the command.
Property | Setting name | Possible values |
---|---|---|
API rate limiter status | com.trendmicro.ds.api:settings.configuration.apiRateLimiterEnabled |
true or false |
User limit | com.trendmicro.ds.api:settings.configuration.apiRateLimiterUserLimit |
Any integer. for example, 500 sets the limit to 500 calls/minute. A negative number allows unlimited calls. |
Tenant limit | com.trendmicro.ds.api:settings.configuration.apiRateLimiterTenantLimit |
Any integer. for example, 1000 sets the limit to 500 calls/minute. A negative number allows unlimited calls. |
Node limit | com.trendmicro.ds.api:settings.configuration.apiRateLimiterNodeLimit |
Any integer. for example, 500 sets the limit to 500 calls/minute. A negative number allows unlimited calls. |
The viewsetting
action uses the following syntax: dsm_c -action viewsetting -name setting_name
The following example displays the status of the rate limiting feature status:
dsm_c -action viewsetting -name com.trendmicro.ds.api:settings.configuration.apiRateLimiterEnabled
The changesetting
command uses the following syntax: dsm_c -action changesetting -name setting_name -value setting_value
The following example changes the user limit to 1000:
dsm_c -action changesetting -name com.trendmicro.ds.api:settings.configuration.apiRateLimiterUserLimit -value 1000
For information about the dsm_c
command, see Command-line basics in the Deep Security Help Center.
Disable rate limiting for a tenant account
If you have multi-tenancy enabled, you can use the Deep Security Manager web page to disable the API rate limiter for specific tenants.
- In the Deep Security Manager console, click Administration > Tenants.
- Open the properties for the tenant.
- On the Features tab, in the Disable Features area, select API Rate Limiter.
- Click OK.
Handle rate limit errors in your code
When an SDK method or function executes when an API rate limit is exceeded in your environment, the method or function throws an ApiException
with the message Too many API calls
. Consider including logic in your code that tests exceptions for this message and if caught, executes the script again after waiting for a certain amount of time.
You can use the APIUsageAPI
class of an SDK to determine call rates. (See API Usage in the API Reference..) For example you can search for all API calls that occur during a certain time period. Parse the returned data to count the total calls. You can also find the number of code 429 responses. (See Date-range searches.)
The following example catches exceptions or errors that are caused when an API rate limit is exceeded. When caught, an exponential backoff algorithm calculates the delay until the call is retried. The number of retries is capped to a maximum number.
while True: # Create a computer object and set the policy ID computer = api.Computer() computer.policy_id = policy_id try: # Modify the computer on Deep Security Manager and store the ID of the returned computer computer = computers_api.modify_computer(computer_ids[change_count], computer, api_version, overrides=False) modified_computer_ids.append(computer.id) retries = 0 # Increment the count and return if all computers are modified change_count += 1 if change_count == len(computer_ids): return modified_computer_ids except api_exception as e: if e.status == 429 and retries < MAX_RETRIES: # The error is due to exceeding an API rate limit retries += 1 # Calculate sleep time exp_backoff = (2 ** (retries +3)) / 1000 print("API rate limit is exceeded. Retry in {} s.".format(exp_backoff)) time.sleep(exp_backoff) else: # Return all other exception causes or when max retries is exceeded return "Exception: " + str(e)
function modifyRecursive(computerID, retry = 0) { return new Promise((resolve, reject) => { // Modify the computer on the manager computersApi .modifyComputer(computerID, computer, apiVersion, { overrides: false }) .then(returnedComputer => { // Resolve the ID of the modified computer resolve(returnedComputer.ID); }) .catch(function(error) { if (error === "Too many API requests." && retry <= max_retries) { // API rate limit is exceeded - calculate retry delay const expBackoff = Math.pow(2, retry + 3); console.log(`API rate limit exceeded. Trying again in ${expBackoff} ms.`); setTimeout(() => { resolve(modifyRecursive(computerID, retry + 1)); }, expBackoff); } else { // Any other errors or maximum retries is exceeded reject(error); } }); }); }
while (modifiedComputerIDs.size() < computerIDs.size()) { // Create a computer and set the policy ID. Computer requestComputer = new Computer(); requestComputer.setPolicyID(policyID); // Modify the computer on Deep Security Manager try { // Index of computer in ComputerIDs to modify in this iteration int i = modifiedComputerIDs.size(); Expand expand = new Expand(); Computer responseComputer = computersApi.modifyComputer(computerIDs.get(i), requestComputer, expand.list(), Boolean.FALSE, apiVersion); modifiedComputerIDs.add(responseComputer.getID()); retries = 0; } catch (ApiException e) { // Check for rate limit error -- calculate sleep time and sleep if (e.getCode() == 429 && retries <= maxRetries) { retries += 1; Double exp_backoff = Double.valueOf(Math.pow(2, retries + 3)); System.out.println(String.format("API rate limit exceeded. Retry in %s ms.", Integer.valueOf(exp_backoff.intValue()))); TimeUnit.MILLISECONDS.sleep(exp_backoff.intValue()); } // Throw exception if not due to rate limiting, or max retries is exceeded else throw (e); } }