Skip to content
You are viewing the latest documentation for Solo Enterprise for kgateway. To access the documentation for older versions, use the version switcher.

Rate limit API requests

Page as Markdown

Protect your portal APIs with rate limiting to control usage, prevent abuse, and enforce fair access across subscriptions.

This guide must be completed by a Portal admin.

Rate limiting controls how many requests a client can make to an API within a given time window. In a developer portal, rate limiting is important for several reasons:

  • Prevent abuse: Stop a single user or application from overwhelming your APIs with excessive requests.
  • Enforce fair usage: Ensure all portal users get consistent, predictable access to shared API resources.
  • Support tiered access: Apply different limits to different subscriptions, so premium or higher-tier users can access APIs at a higher rate than others.
  • Protect backends: Shield upstream services from traffic spikes that could degrade performance or cause outages.

Solo Enterprise for kgateway supports two levels of rate limiting for portal APIs.

  • Default rate limit: You can set a default rate limit that applies to all subscriptions to an API.
  • Subscription-specific rate limits: Portal admins can override the default rate limit with a custom rate limit for a specific subscription by using the portal frontend.

Before you begin

Portal admins must complete the following tasks:

  1. Set up a portal web server.
  2. Secure the login to the portal frontend.
  3. Optional: Set up a backing database for your portal. This database is used to store the rate limit configurations that you create in the Portal frontend app.
  4. Set up API credential management to protect your API product and allow specific rate limit settings for a subscriptions.

Portal users must complete the following tasks:

  1. Create a Team, an app, and a subscription to your app.
  2. Create API credentials so that you can later test the rate limit settings for the API.

Before you begin

Complete the guide to set up credential management for APIs by using API keys or an OAuth client.

Step 1: Set up a default rate limit for an API

You can enforce basic rate limits for an API that automatically applies to all subscriptions to that API. The following example walks you through how to set up a default rate limit for the httpbin API.

  1. Create a RateLimitConfig to limit requests to 2 per minute.

    kubectl apply -f- <<EOF   
    apiVersion: ratelimit.solo.io/v1alpha1
    kind: RateLimitConfig
    metadata:
      name: httpbin-rl
      namespace: default
    spec:
      raw:
        setDescriptors:
          - simpleDescriptors:
              - key: generic_key
                value: counter
            rateLimit:
              requestsPerUnit: 2
              unit: MINUTE
        rateLimits:
          - setActions:
              - genericKey:
                  descriptorValue: counter
    EOF
  2. Create an EnterpriseKgatewayTrafficPolicy that references the RateLimitConfig that you created. Apply the policy to the httpbin HTTPRoute.

    kubectl apply -f- <<EOF
    apiVersion: enterprisekgateway.solo.io/v1alpha1
    kind: EnterpriseKgatewayTrafficPolicy
    metadata:
      name: ratelimit
      namespace: default
    spec:
      targetRefs:
        - group: gateway.networking.k8s.io
          kind: HTTPRoute
          name: httpbin-route
      entRateLimit:
        global:
          rateLimitConfigRefs:
          - name: httpbin-rl
    EOF
  3. Verify that the rate limit is applied. For example, Portal users can follow the steps in View and test API access to send multiple requests to the httpbin API via the frontend app. If you have a valid API key or access token, you can also use the following curl requests. Verify that you are rate limited after 2 successful requests, and that a 429 HTTP response code is returned.

    Cloud Provider Load Balancer:

    for i in {1..3}; do curl -vik ${INGRESS_GW_ADDRESS}:8080/httpbin/headers \ 
     -H "host: api.example.com" \
     -H "api-key: $API_KEY"; done

    Port-forward for local testing:

    for i in {1..3}; do curl -vik localhost:8080/httpbin/headers \ 
     -H "host: api.example.com" \
     -H "api-key: $API_KEY"; done

    Cloud Provider Load Balancer:

    for i in {1..3}; do curl -vik ${INGRESS_GW_ADDRESS}:8080/httpbin/headers \ 
     -H "host: api.example.com" \
     -H "Authorization: Bearer $ACCESS_TOKEN"; done

    Port-forward for local testing:

    for i in {1..3}; do curl -vik localhost:8080/httpbin/headers \ 
     -H "host: api.example.com" \
     -H "Authorization: Bearer $ACCESS_TOKEN"; done

    Example output:

    HTTP/2 200 
    x-powered-by: tinyhttp
    access-control-allow-origin: *
    access-control-allow-methods: GET, HEAD, PUT, PATCH, POST, 
    ...
    
    HTTP/2 200 
    x-powered-by: tinyhttp
    access-control-allow-origin: *
    access-control-allow-methods: GET, HEAD, PUT, PATCH, POST, 
    ...
    
    HTTP/2 429 
    x-envoy-ratelimited: true
    server: envoy

Step 2: Allow overwriting default rate limits via the frontend app

You might want to customize the rate limiting settings for a particular team or app and not use the default rate limiting settings that you applied earlier. To do that, you can use the dynamicMetadata feature in a RateLimitConfig to overwrite any default rate limits with the limits that were configured via the Portal frontend app for a particular API subscription. If no custom rate limit exists for an API subscription, the default rate limits are still enforced.

  1. Update the RateLimitConfig that you created earlier to add the dynamicMetadata feature. In this example, you instruct the portal web server to overwrite the default rate limit settings with the settings for a particular API subscription. The metadataKey path has two entries: the name of the portalAuth section in the AuthConfig that you used when you set up credential management for the API, and rateLimit, which is the key that ExtAuth sets in the dynamic metadata when it processes the subscription. This way, Portal automatically handles all the dynamic metadata that is required to enforce rate limiting for a particular API subscription.

    kubectl apply -f- <<EOF   
    apiVersion: ratelimit.solo.io/v1alpha1
    kind: RateLimitConfig
    metadata:
      name: httpbin-rl
      namespace: default
    spec:
      raw:
        setDescriptors:
          - simpleDescriptors:
              - key: generic_key
                value: counter
            rateLimit:
              requestsPerUnit: 2
              unit: MINUTE
        rateLimits:
          - setActions:
              - genericKey:
                  descriptorValue: counter
            limit:
              dynamicMetadata:
                metadataKey:
                  key: "envoy.filters.http.ext_authz"
                  path:
                    - key: "httpbinAuth"
                    - key: "rateLimit"
    EOF
  2. In your browser, open the portal frontend app, such as http://portal.example.com:8080/ and log in as a Portal admin.

  3. In the frontend app, go to Subscriptions and find the subscription for which you want to rate limit requests.

  4. Click Edit Rate Limit.

  5. Select the number of requests that you want to allow in the Requests Per Unit field and the Unit. For example, you might want to allow a maximum of 5 requests per minute.

  6. Click Save to save your settings.

  7. Verify that the rate limit is applied. For example, Portal users can follow the steps in View and test API access to send multiple requests to the httpbin API via the frontend app. If you have a valid API key or access token, you can also use the following curl requests. Verify that you are rate limited after 5 successful requests instead of 2, and that a 429 HTTP response code is returned.

    Cloud Provider Load Balancer:

    for i in {1..6}; do curl -I ${INGRESS_GW_ADDRESS}:8080/httpbin/headers \ 
     -H "host: api.example.com" \
     -H "api-key: $API_KEY"; done

    Port-forward for local testing:

    for i in {1..6}; do curl -I localhost:8080/httpbin/headers \ 
     -H "host: api.example.com" \
     -H "api-key: $API_KEY"; done

    Cloud Provider Load Balancer:

    for i in {1..6}; do curl -I ${INGRESS_GW_ADDRESS}:8080/httpbin/headers \ 
     -H "host: api.example.com" \
     -H "Authorization: Bearer $ACCESS_TOKEN"; done

    Port-forward for local testing:

    for i in {1..6}; do curl -I localhost:8080/httpbin/headers \ 
     -H "host: api.example.com" \
     -H "Authorization: Bearer $ACCESS_TOKEN"; done

    Example output:

    HTTP/1.1 200 OK
    access-control-allow-credentials: true
    access-control-allow-origin: *
    ...
    
    HTTP/1.1 200 OK
    access-control-allow-credentials: true
    access-control-allow-origin: *
    ...
    
    HTTP/1.1 200 OK
    access-control-allow-credentials: true
    access-control-allow-origin: *
    ...
    
    HTTP/1.1 200 OK
    access-control-allow-credentials: true
    access-control-allow-origin: *
    ...
    
    HTTP/1.1 200 OK
    access-control-allow-credentials: true
    access-control-allow-origin: *
    ...
    
    HTTP/1.1 429 Too Many Requests
    retry-after: 60
    x-envoy-ratelimited: true
    ...
Was this page helpful?