Documentation Index Fetch the complete documentation index at: https://mintlify.com/get-convex/rate-limiter/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The useRateLimit hook provides real-time rate limit information in your React components. It monitors the current rate limit status and automatically updates when capacity changes, allowing you to show users when they can retry an action.
Function Signature
function useRateLimit (
getRateLimitValueQuery : GetRateLimitValueQuery ,
opts ?: UseRateLimitOptions
) : {
status : { ok : true ; retryAt : undefined } | { ok : false ; retryAt : number } | undefined ;
check : ( ts ?: number , count ?: number ) => CheckResult | undefined ;
}
Type Definitions
type GetRateLimitValueQuery = FunctionReference <
"query" ,
"public" ,
GetValueArgs ,
GetValueReturns
>;
type UseRateLimitOptions = {
name ?: string ;
key ?: string ;
count ?: number ;
sampleShards ?: number ;
getServerTimeMutation ?: GetServerTimeMutation ;
config ?: RateLimitConfig ;
};
type GetServerTimeMutation = FunctionReference <
"mutation" ,
"public" ,
Record < string , never >,
number
>;
Parameters
getRateLimitValueQuery
GetRateLimitValueQuery
required
The query function returned by rateLimiter.hookAPI().getRateLimit. This query retrieves the current rate limit value from the server.
Optional configuration object for the hook. The name of the rate limit. If not provided, uses the name from the server configuration.
The key for a per-user/per-session rate limit. Only works if the server-side hookAPI() configuration allows client-provided keys.
The number of tokens to check against. Used to determine if there’s enough capacity for an operation that consumes multiple tokens.
Number of shards to sample when checking rate limit status. Higher values provide more accurate results for sharded rate limits.
A mutation that returns the current server time (Date.now()). Highly recommended for accurate time synchronization between client and server. Use the mutation returned by rateLimiter.hookAPI().getServerTime.
Inline rate limit configuration. Only needed if the rate limit wasn’t defined in the RateLimiter constructor and isn’t provided by the server query.
Return Value
The current rate limit status. undefined while loading. When ok: true: The rate limit check passed - there’s enough capacity.
When ok: false: The rate limit would be exceeded.
Client-time timestamp (in milliseconds) when the action can be retried with enough capacity.
A function to manually check the rate limit at a specific time or for a different token count. Signature : (ts?: number, count?: number) => CheckResult | undefinedClient timestamp to check the rate limit at. Defaults to Date.now().
Number of tokens to check. Defaults to the count from hook options or 1.
Returns CheckResult | undefined: type CheckResult = {
value : number ; // Current token value
ts : number ; // Client timestamp of the value
config : RateLimitConfig ; // The rate limit configuration
shard : number ; // The shard number
ok : boolean ; // Whether the check passed
retryAt ?: number ; // Client timestamp when retry would succeed
}
Usage Example
Basic React Component
import { useRateLimit } from "@convex-dev/rate-limiter/react" ;
import { api } from "./convex/_generated/api" ;
function SendMessageButton () {
const { status , check } = useRateLimit (
api . messages . getRateLimit ,
{
// Recommended: sync client/server clocks
getServerTimeMutation: api . messages . getServerTime ,
// Check if we have capacity for 1 message
count: 1 ,
}
);
if ( ! status ) {
return < button disabled > Loading... </ button > ;
}
if ( ! status . ok ) {
const waitSeconds = Math . ceil (( status . retryAt - Date . now ()) / 1000 );
return (
< button disabled >
Wait { waitSeconds } s before sending
</ button >
);
}
return < button onClick = { handleSend } > Send Message </ button > ;
}
With Manual Checking
function TokenConsumer () {
const [ tokenCount , setTokenCount ] = useState ( 10 );
const { status , check } = useRateLimit (
api . llm . getRateLimit ,
{
getServerTimeMutation: api . llm . getServerTime ,
}
);
// Check if we have capacity for the current token count
const result = check ( Date . now (), tokenCount );
return (
< div >
< input
type = "number"
value = { tokenCount }
onChange = { ( e ) => setTokenCount ( Number ( e . target . value )) }
/>
{ result && (
< div >
{ result . ok ? (
< p > Available capacity: { result . value } tokens </ p >
) : (
< p > Retry in { Math . ceil (( result . retryAt - Date . now ()) / 1000 ) } s </ p >
) }
</ div >
) }
</ div >
);
}
Time Synchronization
The hook uses getServerTimeMutation to synchronize the client and server clocks. This is highly recommended because:
Client clocks can be inaccurate or intentionally set incorrectly
The rate limit calculations happen server-side using server time
Without synchronization, retryAt values may be incorrect
How It Works
// The hook measures latency and calculates the offset
const clientTime = Date . now ();
const serverTime = await convex . mutation ( getServerTimeMutation , {});
const latency = Date . now () - clientTime ;
const timeOffset = serverTime - clientTime - latency / 2 ;
// All times are then adjusted
const adjustedRetryAt = serverRetryTime - timeOffset ;
Server Setup
The getServerTime mutation is automatically included when you use hookAPI():
// In convex/messages.ts
export const { getRateLimit , getServerTime } = rateLimiter . hookAPI (
"sendMessage" ,
{
key : async ( ctx ) => await getUserId ( ctx ),
}
);
Advanced Patterns
See React Hooks Guide for more examples including:
Displaying countdown timers
Optimistic UI updates
Multi-token operations
Custom retry strategies