Skip to main content

Rate limits

Every limit counts requests in a one-minute window. Calls between PipesHub’s own services are not counted. Every limit is kept in each API process. If you run several API replicas, each one counts on its own, so the effective limit can be up to that many times higher. If your load balancer sends a client’s requests to the same replica (session affinity), that replica can return 429 after its own limit even when the others have capacity left. Change a limit in .env and recreate the containers (Docker Compose), or set it in extraEnv in your Helm values and run helm upgrade (see Kubernetes). See Environment variables.

Behind a reverse proxy

Without TRUST_PROXY, PipesHub sees the proxy’s address as the client IP for every request, so everyone who is not signed in shares one bucket. Behind one proxy (Nginx, Caddy, Traefik, a load balancer), set TRUST_PROXY=1, or list the proxy addresses or CIDRs. Never set it to true: clients could then choose their own IP and get around the limits. The Helm chart sets one trusted hop when its ingress is enabled.

The 429 response

A request over a limit gets HTTP 429 with standard RateLimit-* headers and a Retry-After header in seconds:
The message names the limit, for example “Too many authentication requests. Please try again later.” Wait for Retry-After seconds before you retry. Retrying sooner does not help.

Error format

API errors return JSON in this shape:
  • code is stable and safe to branch on. The message text may change.
  • requestId identifies the request in the server logs. Send your own with the X-Request-ID header to match a client log line to the server’s. Include it when you report a problem.
  • Unexpected server failures return 500 with code INTERNAL_ERROR and a generic message. The detail is only in the server log, under the requestId.
Not every route returns every code.