Client Architecture
Relevant source files
The following files were used as context for generating this wiki page:
The Resend client manages interactions with the Resend REST API by providing a high-level interface for email operations, audience management, and account configuration. It acts as a central orchestrator that holds configuration state and exposes various specialized service modules.
The architecture centers on the Resend struct, which contains an Arc<Config> to share settings efficiently across multiple service handles. This design supports both asynchronous and synchronous (blocking) execution modes through conditional compilation features.
Sources: src/lib.rs:48-55, src/config.rs:88-100, README.md:14-18
Core Components
The client architecture consists of three primary layers: the top-level Resend client, the shared Config object, and specialized service structs (e.g., EmailsSvc, ContactsSvc).
The Resend Client
The Resend struct is the main entry point for the SDK. It initializes the configuration and provides public access to different API services. You can instantiate it using Resend::default() or Resend::new(api_key).
Sources: src/client.rs:18-28, src/lib.rs:52-54
Configuration and Transport
The Config struct stores the API key, base URL, and the underlying reqwest HTTP client. It also implements an internal rate limiter for asynchronous environments.
Sources: src/config.rs:88-104, src/client.rs:36-40
Service Pattern
The SDK uses a service-based pattern where specific API domains are grouped into their own structures. Every service struct holds a pub(crate) Arc<Config> to perform requests.
| Service | Module | Purpose |
|---|---|---|
EmailsSvc | src/emails.rs | Sending and managing individual emails. |
BatchSvc | src/batch.rs | Triggering up to 100 emails in a single call. |
ContactsSvc | src/contacts.rs | Managing audience members and custom properties. |
TemplateSvc | src/templates.rs | CRUD operations for email templates. |
AutomationsSvc | src/automations.rs | Managing automated email sequences. |
Sources: src/lib.rs:114-131, src/batch.rs:14-16, src/contacts.rs:31-31
Request Lifecycle
The request flow involves building a URL, applying authentication, and executing the request through a rate limiter.
The Config::build method handles URL path joining to ensure that base URL path prefixes are preserved when using proxies.
Sources: src/config.rs:143-152, src/config.rs:155-165, src/config.rs:205-215
Rate Limiting Architecture
The client enforces rate limits locally to prevent 429 Too Many Requests errors from the Resend API.
- Default Limit: The client defaults to 9 requests per 1.1 seconds.
- Environment Override: You can modify this via the
RESEND_RATE_LIMITenvironment variable. - Async Integration: The rate limiter uses the
governorcrate and only activates in the asynchronous version of the client. - Burst Handling: The limiter allows for bursts based on the configured rate.
Sources: src/lib.rs:6-18, src/config.rs:125-140, README.md:28-32
Environment Configuration
The client automatically detects several environment variables to configure its behavior without code changes.
| Variable | Default Value | Description |
|---|---|---|
RESEND_API_KEY | None | Required for Resend::default(). |
RESEND_BASE_URL | https://api.resend.com | Overrides the target API endpoint. |
RESEND_RATE_LIMIT | 9 | Sets max requests per second (Async only). |
Sources: src/config.rs:115-120, README.md:23-30
Error Handling
The architecture utilizes a custom Error enum to categorize failures.
- Http: Wraps underlying
reqwesterrors. - Resend: Represents structured API errors returned by the server (e.g., validation failures).
- Parse: Occurs when an API response does not match the expected JSON schema or returns HTML during outages.
- RateLimit: Provides structured data (
limit,remaining,reset) when the server enforces its own limits.
Sources: src/lib.rs:260-285, src/config.rs:177-200
Conclusion
The Resend Rust client architecture provides a thread-safe, modular structure that balances ease of use with robust features like automatic rate limiting and environment-based configuration. By sharing a central configuration across specialized services, the SDK remains efficient while offering a clean API for complex email and contact management tasks.