Skip to main content

Rate Limit Guide

The rateLimit module manages per-user, per-bucket, and global rate limits:

  • get/set user rate limits
  • get/set bucket rate limits
  • get/set global rate limits (user, bucket, anonymous scopes)
  • disable rate limits

Requires Ceph Pacific (v16) or later.

API reference: Rate limit types and methods

Prerequisites

import { RadosGWAdminClient } from 'radosgw-admin';

const rgw = new RadosGWAdminClient({
host: 'https://ceph-rgw.example.com',
accessKey: process.env.RGW_ADMIN_ACCESS_KEY!,
secretKey: process.env.RGW_ADMIN_SECRET_KEY!,
});

User Rate Limits

Get User Limit

const limit = await rgw.rateLimit.getUserLimit('alice');
console.log('Read ops/min:', limit.maxReadOps);
console.log('Write ops/min:', limit.maxWriteOps);
console.log('Enabled:', limit.enabled);

Set User Limit

await rgw.rateLimit.setUserLimit({
uid: 'alice',
maxReadOps: 100,
maxWriteOps: 50,
maxWriteBytes: 52428800, // 50 MB/min
enabled: true,
});

Disable User Limit

Disable without changing the configured values:

await rgw.rateLimit.disableUserLimit('alice');

Bucket Rate Limits

Get Bucket Limit

const limit = await rgw.rateLimit.getBucketLimit('my-bucket');
console.log('Read ops/min:', limit.maxReadOps);

Set Bucket Limit

await rgw.rateLimit.setBucketLimit({
bucket: 'my-bucket',
maxReadOps: 200,
maxWriteOps: 100,
enabled: true,
});

Disable Bucket Limit

await rgw.rateLimit.disableBucketLimit('my-bucket');

Global Rate Limits

Global limits apply as defaults across the cluster for a given scope.

Get Global Limits

const global = await rgw.rateLimit.getGlobal();
console.log('Anonymous read limit:', global.anonymous.maxReadOps);
console.log('User default:', global.userRatelimit.maxReadOps);
console.log('Bucket default:', global.bucketRatelimit.maxReadOps);

Set Global Limit

// Limit anonymous access globally
await rgw.rateLimit.setGlobal({
scope: 'anonymous',
maxReadOps: 50,
maxWriteOps: 0, // 0 = unlimited
enabled: true,
});

Available scopes: user, bucket, anonymous.

Rate Limit Values

ValueMeaning
0Unlimited (no restriction)
> 0Ops per minute or bytes per minute
info

Unlike quotas where -1 means unlimited, rate limits use 0 for unlimited. Negative values are invalid.

Per-Instance Behaviour

Rate limits are enforced per RGW instance. If your cluster has 3 RGW daemons and you want a cluster-wide limit of 300 read ops/min, set maxReadOps: 100 on each instance.

const RGW_INSTANCE_COUNT = 3;
const CLUSTER_WIDE_READ_LIMIT = 300;

await rgw.rateLimit.setUserLimit({
uid: 'alice',
maxReadOps: CLUSTER_WIDE_READ_LIMIT / RGW_INSTANCE_COUNT,
enabled: true,
});

Error Handling

import { RGWValidationError, RGWNotFoundError } from 'radosgw-admin';

try {
await rgw.rateLimit.setUserLimit({ uid: 'alice', maxReadOps: 100 });
} catch (error) {
if (error instanceof RGWValidationError) {
// uid is empty or rate limit value is negative
} else if (error instanceof RGWNotFoundError) {
// user does not exist
} else {
throw error;
}
}

Production Notes

  1. Rate limits are per-RGW-instance. Divide your target cluster-wide limit by the number of daemons.
  2. Use anonymous scope to protect public-read buckets from abuse.
  3. Set global defaults first, then override per-user or per-bucket as needed.
  4. Disabling a limit preserves the configured values — re-enabling restores them instantly.
  5. Monitor 429 (Too Many Requests) responses in your application to detect when limits are hit.