Skip to main content

Rate limit requests

You create a request budget, bucket matching traffic by source IP and assign the policy to a group.

Note: Balancer is in beta. Endpoints, fields and behavior may change before general availability, and the feature must be enabled on your account before use. Contact your NetActuate account manager to request access.

Prerequisites​

  • Balancer access and a key in the BALANCER_API_KEY environment variable with permission for these operations.
  • The API host shown in the Balancer portal. Replace <your-api-host> in every example with that host.
  • A shell, curl and Python 3 for examples that build JSON from environment variables.
  • An HTTP group and a controlled /api/ test path. Review source allow rules, because a source allow match bypasses the budget path.

Resource identifiers come from your API responses. Set each variable when its value is available, before the first step that uses it.

Environment variableValue
GROUP_IDReturned resource identifier, or your selected scope identifier.
HTTP_LB_IDReturned resource identifier, or your selected scope identifier.
RATE_LIMIT_POLICY_IDReturned resource identifier, or your selected scope identifier.

For an identifier, enter the value returned for your resource and export it:

read -r -p 'GROUP_ID: ' GROUP_ID
export GROUP_ID

Steps​

  1. Create a policy.

    curl --silent --show-error --include \
    --request POST \
    --url "https://<your-api-host>/rate-limit-policies" \
    --header "x-api-key: $BALANCER_API_KEY" \
    --header "Content-Type: application/json" \
    --data-binary '{"name":"api_budget","isGlobal":false}'

    API reference: Create a reusable rate-limit policy

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "rateLimitPolicyId": 1
    }
    }

    Set RATE_LIMIT_POLICY_ID to the returned rateLimitPolicyId.

  2. Validate the expression.

    curl --silent --show-error --include \
    --request POST \
    --url "https://<your-api-host>/rate-limit-policies/validate-request-expression" \
    --header "x-api-key: $BALANCER_API_KEY" \
    --header "Content-Type: application/json" \
    --data-binary '{"requestExpression":"starts_with(http.request.uri.path, \"/api/\")"}'

    API reference: Validate a rate-limit request expression in your account

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success"
    }
  3. Add a rule with the required priority.

    curl --silent --show-error --include \
    --request POST \
    --url "https://<your-api-host>/rate-limit-policies/$RATE_LIMIT_POLICY_ID/rules" \
    --header "x-api-key: $BALANCER_API_KEY" \
    --header "Content-Type: application/json" \
    --data-binary '{"priority":10,"rule":{"ruleId":"api_per_ip","requestExpression":"starts_with(http.request.uri.path, \"/api/\")","bucketBy":[{"field":"sourceIp","isRequired":true}],"limit":{"amount":10,"periodSeconds":1,"burst":10},"charge":{"timing":"request","requestCost":{"kind":"weightedRequests","weight":1}},"chargeBlockedAttempts":false}}'

    API reference: Create a rate-limit policy rule

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "rateLimitPolicyRuleId": 1
    }
    }
  4. Assign the policy.

    python3 - <<'PYBODY' | \
    curl --silent --show-error --include \
    --request PATCH \
    --url "https://<your-api-host>/http-loadbalancers/$HTTP_LB_ID/groups/$GROUP_ID" \
    --header "x-api-key: $BALANCER_API_KEY" \
    --header "Content-Type: application/json" \
    --data-binary @-
    import json, os
    print(json.dumps({'rateLimitPolicyId': int(os.environ['RATE_LIMIT_POLICY_ID'])}))
    PYBODY

    API reference: Update an HTTP group configuration

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "groupId": 1
    }
    }
  5. Read the saved rule and group assignment.

    curl --silent --show-error --include \
    --request GET \
    --url "https://<your-api-host>/rate-limit-policies/$RATE_LIMIT_POLICY_ID/rules" \
    --header "x-api-key: $BALANCER_API_KEY"

    API reference: List rate-limit policy rules

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success"
    }
  6. Check the effective group.

    curl --silent --show-error --include \
    --request GET \
    --url "https://<your-api-host>/http-loadbalancers/$HTTP_LB_ID/groups/$GROUP_ID" \
    --header "x-api-key: $BALANCER_API_KEY"

    API reference: Get HTTP group

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "groupId": 1
    }
    }

Verify​

Send controlled requests to /api/ from the same source IP. Check allowed responses, then 429 responses when the balance is already negative, and recovery after replenishment. The current request is allowed at a nonnegative balance even if its cost makes the resulting balance negative. Do not expect rejection precisely when the current cost exceeds the remaining balance.

Use your configured site domain in this traffic check:

curl --silent --show-error --include "https://example.com/api/"

Expected: the site behavior described above. The application response body and status depend on your origin and selected policies.

An API mutation saves desired configuration first. Readback and a live traffic check answer different questions. No fixed propagation time is established.

Rules are ordered and the first matching rule returns the budget decision. A top-level source allow policy differs from a WAF allow policy, which is evaluated after the budget.

Troubleshooting​

SymptomCauseFix
One additional request succeedsThe balance was nonnegative before chargingUse the pre-charge negative-balance rule when evaluating results.
Rule creation returns 400priority or required rule fields are missingSupply priority, ruleId, requestExpression, bucketBy and limit.
Request returns 502A required bucket input is missingCheck bucket fields and isRequired.
429 occurs before expected exhaustionBucket cardinality pressure can also reject requestsInspect attribution and bucket selection before raising the amount.
No rule is chargedEarlier source allow or another first matching rule winsCheck effective assignment, priority and expression.

Limits and defaults​

SettingLimit or default
PriorityRequired; 1 to 100000000
Bucket fields per rule1 to 16
PeriodDefault 1 second; 1 to 86400 seconds
BurstDefaults to limit.amount
ChargingRequest timing only; default request weight 1
Blocked attemptsNot charged by default
isGlobalDefault false
429 responseHTML; Cache-Control: no-store; no Retry-After header

API status codes​

StatusMeaning
200Request succeeds; inspect returned data.
400Invalid arguments or configuration.
401Authentication or authorization denied.
404Resource or parent is unavailable.
409Resource state conflicts with the operation.
412Inspect the returned error details.
500The request encounters a server error.
503The operation is temporarily unavailable.
  • DELETE /rate-limit-policies/{rateLimitPolicyId}
  • DELETE /rate-limit-policies/{rateLimitPolicyId}/rules/{rateLimitPolicyRuleId}
  • GET /http-loadbalancers/{httpLbId}/groups/{groupId}
  • GET /rate-limit-policies
  • GET /rate-limit-policies/{rateLimitPolicyId}
  • GET /rate-limit-policies/{rateLimitPolicyId}/rules
  • GET /rate-limit-policies/{rateLimitPolicyId}/rules/{rateLimitPolicyRuleId}
  • PATCH /http-loadbalancers/{httpLbId}/groups/{groupId}
  • PATCH /rate-limit-policies/{rateLimitPolicyId}
  • PATCH /rate-limit-policies/{rateLimitPolicyId}/rules/{rateLimitPolicyRuleId}
  • POST /rate-limit-policies
  • POST /rate-limit-policies/validate-request-expression
  • POST /rate-limit-policies/{rateLimitPolicyId}/rules

API reference​

Need Help?​

Contact your account manager or use the Balancer portal.