# `X402.RateLimiter.ETS`
[🔗](https://github.com/cardotrejos/x402/blob/v0.9.0/lib/x402/rate_limiter/ets.ex#L1)

Per-node fixed-window rate limiter backed by a lazily created ETS table.

Each key owns one counter per window: the first hit opens a window of
`window_ms` and every hit until it closes increments the counter, so a
key may make at most `limit` hits per window. Once the window closes the
next hit opens a fresh one. Fixed windows admit up to `2 × limit` hits
across a window boundary; pick `limit`/`window_ms` with that in mind.

The table is created on first use and needs no process in your
supervision tree. Stale windows are swept opportunistically (every
1000 hits) and can be swept explicitly with `sweep/1`.

> #### Per-node only {: .warning}
>
> Counters live on the local node. In a clustered deployment each node
> limits independently, so a wallet load-balanced across `n` nodes gets
> up to `n × limit` hits per window. Use a shared-store implementation of
> `X402.RateLimiter` when that matters.

# `table`

```elixir
@type table() :: atom()
```

ETS table name holding the counters.

# `hit`
*since 0.9.0* 

```elixir
@spec hit(table() | nil, X402.RateLimiter.key(), pos_integer(), pos_integer()) ::
  X402.RateLimiter.result()
```

Records a hit for `key` in the fixed window of `window_ms` milliseconds.

`table` is the ETS table name; `nil` selects the default table.

## Examples

    iex> table = String.to_atom("rate_limiter_doctest_122916")
    iex> X402.RateLimiter.ETS.hit(table, {:payer, "0xabc"}, 2, 60_000)
    {:allow, 1}
    iex> X402.RateLimiter.ETS.hit(table, {:payer, "0xabc"}, 2, 60_000)
    {:allow, 0}
    iex> {:deny, retry_after_ms} = X402.RateLimiter.ETS.hit(table, {:payer, "0xabc"}, 2, 60_000)
    iex> retry_after_ms in 1..60_000
    true

# `reset`
*since 0.9.0* 

```elixir
@spec reset(table() | nil) :: :ok
```

Clears every counter in the table.

# `sweep`
*since 0.9.0* 

```elixir
@spec sweep(table() | nil) :: non_neg_integer()
```

Removes windows that have already closed.

Returns the number of rows removed.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
