Recipe

Apply different rate limiting policies to separate apps/APIs

How to use this recipe

1. Define your internal agent endpoints and rate limiting rules

Assuming that your API services run on the same system or are accessible on the same network, you can use a single ngrok agent and the configuration file to create multiple agent endpoints.

version: 3

agent:
  authtoken: $YOUR_NGROK_AUTHTOKEN

endpoints:
  - url: https://foo.internal
    upstream:
      url: 8080
    traffic_policy:
      on_http_request:
        - actions:
            - type: rate-limit
              config:
                name: Allow 100 requests per minute
                algorithm: sliding_window
                capacity: 100
                rate: 60s
                bucket_key:
                  - conn.client_ip
  - name: bar
    url: https://bar.internal
    upstream:
      url: 8081
    traffic_policy:
      on_http_request:
        - actions:
            - type: rate-limit
              config:
                name: Allow 500 requests per minute
                algorithm: sliding_window
                capacity: 500
                rate: 60s
                bucket_key:
                  - conn.client_ip
Tip: If your services run on different machines, you can also use the ngrok agent with a Traffic Policy file and the --traffic-policy-file argument.

2. Start your internal agent endpoints

On the server where ngrok and your services run, start ngrok and your endpoints.

ngrok start foo bar

3. Reserve a domain

Navigate to the Domains section of the ngrok dashboard and click New + to reserve a domain like https://your-api.ngrok.app, which we’ll refer to $YOUR_NGROK_DOMAIN from here on out.

4. Create a cloud endpoint

Navigate to the Endpoints section of the ngrok dashboard, then click New + and Cloud Endpoint to create a new cloud endpoint on $YOUR_NGROK_DOMAIN.

5. Apply Traffic Policy to your cloud endpoint for path-based routing

With CEL interpolation, which takes the request's path and removes the leading forward slash, you can route requests from https://$YOUR_NGROK_DOMAIN/foo to https://foo.internal and so on.

on_http_request:
  - actions:
      - type: forward-internal
        config:
          url: https://${req.url.path.split("/")[1]}.internal

What you get from this recipe

You now have multiple services publicly accessible on a single hostname and path-based routing, but with different rate limiting limits based on the nature of the service, how expensive it is to run, or how often you expect clients to use them.

Plus, by composing the rate limiting rules on the agent endpoints instead of the cloud endpoint, you've created a separation of concerns between your "front door" infrastructure and the lifecycle of your individual upstream services. That "shape" makes your Traffic Policy configures more modular, instead of relying on a single verbose configuration to do all traffic management work.

What's next?