Help us shape the future of Go! Take the 2026 Go Developer Survey

throttle

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 10, 2026 License: AGPL-3.0 Imports: 6 Imported by: 0

Documentation

Overview

Package throttle implements counter-based rate limiting for the auth surface, backed by the auth_throttle table. The model is fixed-window: each (scope, identifier) pair has a hit counter that resets when the window has elapsed.

We deliberately use Postgres rather than introducing Redis. At launch scale this is well within Postgres's comfort zone, and avoiding a new dependency is worth the marginal latency. Migrate if S36 proves it necessary.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsThrottled

func IsThrottled(err error) bool

IsThrottled is the canonical predicate for distinguishing a throttle rejection from a generic error.

Types

type DBTX

type DBTX = usersdb.DBTX

DBTX matches sqlc's DBTX so callers can pass a *pgxpool.Pool or a transaction interchangeably.

type ErrThrottled

type ErrThrottled struct {
	RetryAfter time.Duration
	Hits       int
}

ErrThrottled is returned by Hit when the policy's limit is exceeded. RetryAfter carries a hint suitable for the HTTP `Retry-After` header.

func (*ErrThrottled) Error

func (e *ErrThrottled) Error() string

type Limit

type Limit struct {
	Scope      string        // e.g. "login", "signup", "reset"
	Identifier string        // e.g. "ip:1.2.3.4|alice"
	Max        int           // hits permitted within Window
	Window     time.Duration // sliding-fixed window length
}

Limit is a (scope, identifier, max-hits, window) policy.

type Limiter

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

Limiter holds the queries handle. Construct with NewLimiter.

func NewLimiter

func NewLimiter() *Limiter

NewLimiter returns a limiter bound to the sqlc queries package.

func (*Limiter) Hit

func (l *Limiter) Hit(ctx context.Context, db DBTX, p Limit) error

Hit increments the counter for the policy. Returns nil if under the limit, ErrThrottled (with RetryAfter) if at or over.

The query is conditional: if the existing window started before (now - policy.Window) we treat it as a new window and reset hits to 1. Otherwise we increment in place. The work happens atomically inside Postgres so concurrent requests don't undercount.

func (*Limiter) Purge

func (l *Limiter) Purge(ctx context.Context, db DBTX, olderThan time.Duration) error

Purge deletes throttle rows older than cutoff. Caller is expected to run this on a periodic schedule (S14 worker).

func (*Limiter) Reset

func (l *Limiter) Reset(ctx context.Context, db DBTX, scope, identifier string) error

Reset clears the counter for (scope, identifier). Used after a successful login to forgive prior failed attempts on the same key.

Jump to

Keyboard shortcuts

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