Token bucket rate limiter backed by ETS.
Provides global and per-actor rate limiting for MCP tool calls. Designed for LLM clients that may make rapid consecutive requests.
Configuration
Configure globally in config.exs:
config :ectomancer, :rate_limit,
max: 100,
window_ms: 60_000,
per_actor: falseOr inline in use Ectomancer:
use Ectomancer,
name: "my-app",
rate_limit: [max: 100, window_ms: 60_000]Algorithm
Token bucket with self-refilling tokens. On each request:
- Read bucket state
{key, tokens, last_refilled_at} - Calculate new tokens based on elapsed time since last refill
- Cap at
max(burst capacity) - If >= 1 token available: consume one, write new state
- If no tokens: return
{:error, :rate_limited, retry_after_ms}
Summary
Functions
Checks if a request is within configured rate limits.
Initializes the ETS table. Idempotent — safe to call multiple times.
Resets all rate limit buckets. Useful for testing.
Functions
@spec check(keyword()) :: :ok | {:error, :rate_limited, non_neg_integer()}
Checks if a request is within configured rate limits.
Options
:max— Maximum token capacity (burst limit). Default:100:window_ms— Refill window in milliseconds. Default:60_000:key— Bucket identifier. Default::global
Returns
:ok— Request allowed, one token consumed{:error, :rate_limited, retry_after_ms}— Denied, suggests retry delay
@spec init() :: :ok
Initializes the ETS table. Idempotent — safe to call multiple times.
@spec reset() :: :ok
Resets all rate limit buckets. Useful for testing.