How Rate Limiting for External API Calls Works in the Macro Repository

Macro implements rate limiting for external API calls using a Redis-backed sliding-window algorithm executed atomically via Lua scripts, with cost-based quota consumption for operations like Gmail and Google Calendar API calls.

The macro-inc/macro repository manages high-volume outbound requests to third-party services such as Gmail and Google Calendar. To prevent quota exhaustion and ensure fair resource distribution across distributed instances, the codebase centralizes rate limiting for external API calls in Redis with atomic enforcement.

Redis-Backed Sliding-Window Architecture

The RedisClient Wrapper

The rate limiting infrastructure centers on RedisClient, defined in the redis crate, which encapsulates configuration for quota management. This wrapper holds rate_limit_units (the maximum quota capacity per window) and rate_limit_secs (the sliding window duration in seconds). By storing state in Redis rather than in-memory, the system guarantees consistent enforcement across all service instances without race conditions.

Cost-Based Quota System

Rather than treating all requests equally, Macro employs a cost-based approach where each API operation implements a cost() method. For example, GmailApiOperation::cost() returns the number of quota units a specific operation consumes, allowing fine-grained control where complex operations (like full message fetches) consume more quota than lightweight operations (like listing message IDs).

The Atomic Lua Script Implementation

The core enforcement logic resides in services/email_service/src/util/redis/rate_limit.rs. Two primary methods handle rate limit checks:

  • RedisClient::is_rate_limited – For Gmail operations, using keys formatted as gmail-ratelimit:log:<user_id>
  • RedisClient::is_calendar_rate_limited – For Calendar operations, using keys formatted as calendar-ratelimit:log:<email_link_id>

These methods generate unique Redis members formatted as "<cost>:<uuid>" and invoke the Lua script via redis::Script::new. The script, retrieved through get_rate_limit_script_with_usage, performs three atomic operations:

  1. Cleanup – Removes entries older than the sliding window
  2. Aggregation – Sums the costs of remaining entries
  3. Enforcement – Determines if adding the new request cost would exceed the configured limit

The Lua script returns a tuple [is_limited, unit_count] where is_limited == 1 indicates the request should be blocked, eliminating "check-then-set" race windows through atomic execution.

Back-Fill vs. Interactive Traffic

When the is_backfill flag is set to true, the system applies rate_limit_units_backfill—a lower threshold that ensures background synchronization jobs do not starve normal interactive traffic. This prioritization guarantees that user-facing operations receive quota priority over historical data back-filling.

Practical Implementation Examples

The following pattern demonstrates checking rate limits before invoking the Gmail API:

use macro_env_var::env;
use services::email_service::util::redis::{
    RedisClient, RateLimitArgs,
};
use models_email::gmail::operations::GmailApiOperation;

// Initialise a Redis client (configuration comes from Doppler/env vars)
let redis = RedisClient::new(env!("REDIS_URI")).await?;

// Prepare arguments for a Gmail "list messages" operation
let args = RateLimitArgs {
    user_id: user_uuid,
    operation: GmailApiOperation::ListMessages,
    is_backfill: false,
};

// Perform the rate-limit check before issuing the HTTP request
if redis.is_rate_limited(args).await {
    // The user has exhausted their quota; delay or abort the request
    tracing::info!("Rate limited for user {}", user_uuid);
    return Err(YourError::RateLimited);
}

// Otherwise the call is allowed – proceed to invoke the Gmail API
let gmail = GmailApi::new(&redis).await?;
let messages = gmail.list_messages(...).await?;

For Google Calendar operations, the implementation uses a fixed cost approach through the dedicated calendar method:

// Calendar example – uses the same sliding-window script but a fixed cost of 1
let calendar_limited = redis.is_calendar_rate_limited(email_link_id).await;
if calendar_limited {
    tracing::warn!("Calendar rate limit hit for link {}", email_link_id);
    // Handle back-off or retry logic here
}

Key Source Files and Components

Summary

  • Macro uses a Redis-backed sliding-window rate limiter for all external API calls, ensuring consistent enforcement across distributed service instances.
  • Cost-based quota consumption allows different API operations to consume varying amounts of quota via the cost() method on operation types.
  • Atomic Lua scripts eliminate race conditions by combining cleanup, aggregation, and enforcement into a single Redis operation.
  • Back-fill prioritization uses separate rate_limit_units_backfill limits to protect interactive traffic from background job saturation.
  • Service-specific implementations in services/email_service/src/util/redis/rate_limit.rs handle Gmail and Calendar APIs with distinct Redis key schemas.

Frequently Asked Questions

What type of rate limiting algorithm does Macro use?

Macro implements a sliding-window rate limiting algorithm backed by Redis. Unlike fixed-window approaches, this tracks the exact timestamp of each request within the configured window duration (rate_limit_secs), providing smoother quota distribution and preventing thundering herd issues at window boundaries.

How does Macro handle different costs for different API operations?

Each API operation type implements a cost() method (such as GmailApiOperation::cost()) that returns an integer representing quota units consumed. When checking limits, the system formats Redis members as "<cost>:<uuid>", allowing the Lua script to sum actual costs rather than just counting requests. This enables expensive operations (like fetching full message bodies) to consume more quota than cheap operations (like listing message metadata).

What is the purpose of the back-fill flag in the rate limiter?

The is_backfill boolean flag indicates whether the request originates from a background synchronization job rather than user-initiated traffic. When true, the rate limiter applies rate_limit_units_backfill—a lower threshold than the standard rate_limit_units—ensuring that historical data imports do not exhaust quotas needed for real-time user interactions.

Why does Macro use Lua scripts for rate limiting?

Macro uses Lua scripts via redis::Script::new to guarantee atomicity during the check-and-set operation. Without Lua, separate Redis commands for cleanup, sum calculation, and limit enforcement would create race conditions where concurrent requests could both pass the check before either updates the counter. The Lua script executes entirely on the Redis server, reducing round-trips and ensuring consistent state even under high concurrency.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →