Rate limits and quotas
A fixed window per API key, per user, or per tenant, in one command on the shard that owns the key.
LIMIT key max window_ms returns the remaining allowance, or a null bulk when the window is full. A rejected call is not counted. The window is the key's deadline, so a quiet key disappears by itself. In WAL-backed modes the accepted call is a log record.
Keep in mindFixed window, not sliding. If you need per-second smoothing on top, keep a short second window next to the long one.
ReferenceLIMIT
.NET packageRuvio.AspNetCore.RateLimiting
LIMIT api:key-7 100 60000
# 99 -> 99 calls left in this 60 s window
# (nil) -> window is full, nothing was counteduse ruvio_client::Client;
let mut db = Client::connect("127.0.0.1", 6379)?;
let left = db.limit("api:key-7", 100, 60_000)?;
// Some(99) -> 99 calls left in this 60 s window
// None -> window is full, nothing was countedawait using var connection = await RuvioConnection.ConnectAsync("127.0.0.1", 6379);
var db = await connection.GetDefaultDatabaseAsync();
long? left = await db.LimitAsync("api:key-7", 100, 60_000);
// 99 -> 99 calls left in this 60 s window
// null -> window is full, nothing was countedc, err := ruvio.Connect(ctx, ruvio.Options{Addr: "127.0.0.1:6379"})
if err != nil { return err }
left, ok, err := c.Limit(ctx, "api:key-7", 100, time.Minute)
if err != nil { return err }
fmt.Println(left, ok)
// 99 true -> 99 calls left in this 60 s window
// 0 false -> window is full, nothing was countedvar c = RuvioClient.connect("127.0.0.1", 6379);
Long left = c.limit("api:key-7", 100, 60_000);
// 99 -> 99 calls left in this 60 s window
// null -> window is full, nothing was countedimport ruvio
r = ruvio.Ruvio("127.0.0.1", 6379)
left = r.limit("api:key-7", 100, 60_000)
# 99 -> 99 calls left in this 60 s window
# None -> window is full, nothing was countedimport { createClient } from 'ruvio-client';
const c = createClient({ host: '127.0.0.1', port: 6379 });
const left = await c.limit('api:key-7', 100, 60_000);
// 99 -> 99 calls left in this 60 s window
// null -> window is full, nothing was countedbuilder.Services.AddRuvioClient(builder.Configuration.GetSection("Ruvio"));
builder.Services.AddRuvioRateLimiting(options =>
{
options.KeyPrefix = "orders:rate:v1:";
options.PartitionKey = context =>
context.User.FindFirst("tenant_id")?.Value
?? throw new InvalidOperationException("An authenticated tenant is required.");
});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseRuvioRateLimiting();
app.MapPost("/orders", HandleOrder)
.RequireAuthorization()
.WithMetadata(new RuvioRateLimitAttribute("create-order", permits: 100, windowSeconds: 60));