Skip to content

Results and HTTP headers

Every limiter decision returns core.Result plus an error. Treat the error as the execution status and Allowed as the policy decision.

core.Result

Field Meaning
Allowed The current request may proceed
Limit Configured whole-request capacity
Remaining Whole-request capacity remaining after this decision
Reset Duration until full reset or refill if no more requests arrive
RetryAfter Earliest reliable retry delay for a denied request

Reset and RetryAfter are relative time.Duration values. A zero duration means that no positive, reliable duration was returned; it does not necessarily mean “retry immediately.”

Decision flow

sequenceDiagram
    accTitle: Limiter result and failure sequence
    accDescr: The application calls the limiter, which updates state and returns a normal decision, fail-closed error, or fail-open allowance.
    participant App
    participant Limiter
    participant Store
    App->>Limiter: Allow(ctx, key)
    Limiter->>Store: Read and update state
    alt successful evaluation
        Store-->>Limiter: state transition
        Limiter-->>App: Result, nil
    else fail closed
        Store-->>Limiter: error
        Limiter-->>App: Allowed=false, error
    else fail open
        Store-->>Limiter: error
        Limiter-->>App: Allowed=true, nil
    end

Middleware header mapping

The bundled adapters use the same mapping:

Header Source Emitted when Wire value
RateLimit-Limit Result.Limit Successful limiter call Decimal integer
RateLimit-Remaining Result.Remaining Successful limiter call Decimal integer
RateLimit-Reset Result.Reset Duration is positive Ceiling of seconds
Retry-After Result.RetryAfter Request is denied and duration is positive Ceiling of seconds

RateLimit-Reset is emitted as a relative number of seconds by the current implementation, not as a Unix timestamp. Retry-After uses the HTTP delta- seconds form.

Allowed requests continue to the application handler. Denied requests receive HTTP 429 Too Many Requests by default. Fail-closed backend errors receive HTTP 500 by default and do not receive rate-limit headers because middleware handles the error before mapping a result.

Failure-policy nuance

On a runtime backend error with FailOpen: true, GoRL returns an allowed result with the configured Limit, zero Remaining, and zero timing fields. Bundled middleware therefore emits RateLimit-Limit and RateLimit-Remaining: 0 while allowing the request. Do not interpret remaining capacity during a fail-open event as authoritative.

Custom responses

Use the middleware-specific denied and error handlers when your API needs a stable error schema, trace ID, localized message, or additional logging. Keep the limiter metadata as the source of truth instead of recomputing retry times in the handler.