Documentation
¶
Overview ¶
Package ratelimitpg shares rate limits across instances in PostgreSQL (ADR-0052). A Limiter implements ratelimit.Taker with GCRA, the generic cell rate algorithm: each key keeps one row with its theoretical arrival time, and one statement decides and records a request, so every instance sees the same budget with the same rate-and-burst behaviour as the in-memory limiter. Keys are stored hashed.
Two in-memory limiters protect it:
- a local pre-check with twice the burst refuses a client far over its limit without touching the database, so a flood of requests can't become a flood of writes;
- a fallback with the same limit decides when the database doesn't answer within DecisionTimeout, and a warning is logged at most once a minute per limiter, so requests keep working with per-instance limits during an outage.
Stability: stable (ADR-0015, ADR-0054).
Index ¶
Constants ¶
const ( // DecisionTimeout bounds each database decision. DecisionTimeout = 250 * time.Millisecond )
Variables ¶
var Migrations fs.FS = mustSub(migrationFiles, "migrations")
Migrations holds the module's goose migrations: the ratelimit_buckets table. Apps copy them into db/migrations; tests can apply them directly with pgtest.
Functions ¶
This section is empty.
Types ¶
type Limiter ¶
type Limiter struct {
// contains filtered or unexported fields
}
Limiter shares one limit across instances. Limiters with the same name on any instance share their keys' budgets. It is safe for concurrent use.
type Option ¶
type Option func(*Store)
An Option configures a Store.
func WithLogger ¶
WithLogger sets the logger for fallback warnings. Default: discard.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store holds the shared buckets of every limiter. It is safe for concurrent use.
func NewStore ¶
NewStore returns a store on pool, which must have the module's migrations applied. Decisions count the OpenTelemetry metrics ratelimit.decisions and ratelimit.fallbacks.
func (*Store) DeleteExpired ¶
DeleteExpired removes up to limit buckets whose keys are back to a full budget, so the table holds only recently limited keys. Apps run it from a periodic job.
func (*Store) Limiter ¶
Limiter returns the limiter name, whose limit is read on every decision, so a limit backed by a runtime setting applies at once. The name is part of every key: use one name per kind of limit, such as auth_login.