throttle

package
v0.2.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 9, 2026 License: MPL-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package throttle is a small per-key fixed-window rate limiter. It exists to gate the chassis's unsigned credential-mint endpoints (`/auth/dev/enroll`, `/auth/invitations/consume`) against brute-force probing without dragging in a full rate-limit library.

Sizing rationale: state is one int + one timestamp per active key (typically the caller's IP). Lazy cleanup on every Allow evicts buckets older than 2× the window so the map stays bounded under churn even when long-lived attackers cycle through IPs.

What this is NOT:

  • distributed (single process; restart resets counters)
  • sliding-window (boundary-burst behaviour is acceptable for our anti-abuse threat model)
  • per-user (caller carries no identity at the gate; that's the point of throttling unsigned endpoints)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Throttle

type Throttle struct {
	// contains filtered or unexported fields
}

Throttle is a per-key fixed-window counter. Zero value is not usable — call New.

func New

func New(limit int, window time.Duration) *Throttle

New returns a Throttle that admits up to `limit` attempts per `window` per key.

limit == 0 (or negative) disables the throttle: every Allow call returns ok=true. This is the cheap kill switch used by tests and by operators setting TXCO_THROTTLE_DISABLED=1.

window must be positive when limit > 0; a zero window would make every attempt count toward the same eternal bucket. The constructor clamps to 1s in that case rather than panicking — defensive against env-misconfiguration without surfacing an error to startup.

func (*Throttle) Allow

func (t *Throttle) Allow(key string) (bool, time.Duration)

Allow records an attempt for key. Returns (true, 0) when the attempt is below threshold (and the count has been bumped); returns (false, retryAfter) when the bucket is exhausted, where retryAfter is the remaining duration in the current window.

Disabled throttles (limit==0) always return (true, 0) without touching state.

Side effect: lazy cleanup of stale buckets. On each call we sweep the map and drop any bucket whose resetAt is more than `window` in the past — that's twice the active-window age, so we never evict a bucket that's still counting. Cleanup is O(n) in map size but n is bounded by recent unique callers, which is small in practice.

func (*Throttle) Size

func (t *Throttle) Size() int

Size returns the number of live buckets. Exported for tests that assert the lazy cleanup actually evicts; not intended for callers to inspect at runtime.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL