Introduction
The modern, type-safe rate limiting library for Python and TypeScript.
Halt is designed to be the last rate limiter you'll ever need. Whether you're building a simple API or a complex multi-tenant SaaS platform, Halt provides the primitives and high-level abstractions to protect your resources effectively.
Prefer to skip the reading?
Answer four questions and the interactive builder writes the exact setup for your stack.
At a Glance
Performance First
Optimized for low latency with O(1) memory usage per key and efficient storage patterns.
SaaS Ready
Built-in support for multi-tenancy, quotas, tiered plans, and penalty systems.
Storage Agnostic
First-class support for Redis, Postgres, MongoDB, DynamoDB, Memcached, and Memory.
Developer Experience
Fully typed, intuitive APIs, and comprehensive documentation for both Python and TS.
How it Works
graph LR
Client[Client] --> LB[Load Balancer]
LB --> App[Application / Middleware]
subgraph Halt Logic
App -- Check Limit --> Limiter[Rate Limiter]
Limiter -- Get/Set --> Store[(Storage Backend)]
Store -- Result --> Limiter
Limiter -- Allowed/Blocked --> App
end
App --> API[API Logic]Halt intercepts requests at the application or middleware layer, checks usage against the storage backend, and decides whether to allow or block the request.
Simple Example
Protecting an endpoint is as simple as defining a limiter and applying it.
Python
import redis
from halt import RateLimiter, RedisStore, presets
limiter = RateLimiter(
store=RedisStore(client=redis.Redis.from_url("redis://localhost:6379")),
policy=presets.PUBLIC_API,
)
if not limiter.check("user:123").allowed:
raise RateLimitExceeded()TypeScript
import Redis from 'ioredis';
import { RateLimiter, RedisStore, presets } from 'halt-rate';
const limiter = new RateLimiter({
store: new RedisStore({ client: new Redis(process.env.REDIS_URL) }),
policy: presets.PUBLIC_API
});
const result = await limiter.check("user:123");
if (!result.allowed) {
throw new RateLimitExceeded();
}