How to Access Environment Variables in Macro: The Complete Guide to macro_env_var
The Macro codebase requires all environment variables be accessed in Macro through the dedicated macro_env_var crate, which provides compile-time macros that enforce validation, optional handling, and centralized secret management.
When you access environment variables in Macro, you must avoid direct calls to std::env::var or std::env::var_os. According to the macro-inc/macro repository standards, the macro_env_var crate serves as the single, sanctioned wrapper for all configuration and secret access. This architectural policy ensures that missing variables surface immediately at startup and that sensitive values can be fetched from remote secret managers like Doppler or AWS Secrets Manager in one centralized location.
Why Macro Uses a Dedicated Environment Variable Crate
The enforcement of macro_env_var as the sole access point appears explicitly in the source at /crates/macro_env_var/src/lib.rs at line 11, which states this crate is the sanctioned wrapper around standard environment access. This design delivers three critical benefits:
- Security: Centralizing access allows the team to implement secret-fetching logic, encryption, and auditing in a single codebase location rather than scattering it across dozens of services.
- Consistency: Every service—from the Authentication Service to the Native App Server—follows identical patterns for loading configuration, making audits straightforward.
- Testability: The macros can be stubbed or overridden in unit tests, allowing deterministic behavior without modifying the actual process environment.
The Core Macros for Environment Access
The macro_env_var crate exposes declarative macros that handle distinct access patterns. These compile-time utilities generate code that validates state at startup.
env_var! for Mandatory Variables
Use env_var! when a variable must exist for the service to function. It returns a String (or a parsed type) and panics immediately if the variable is unset or empty, ensuring services fail fast during initialization rather than at runtime.
use macro_env_var::env_var;
let db_url = env_var!("POSTGRES_URL");
// Panics if POSTGRES_URL is not set
maybe_env_var! for Optional Configuration
Use maybe_env_var! when a variable is truly optional. It returns Option<String>, yielding None when the variable is unset or empty. This pattern appears in /crates/macro_aws_config/src/lib.rs at line 6 for optional AWS credential loading.
use macro_env_var::maybe_env_var;
let redis_url = maybe_env_var!("REDIS_URL");
// Returns None if REDIS_URL is not set
env_vars! for Bulk Mandatory Loading
Use env_vars! to read multiple required variables at once, returning a generated struct with fields matching the variable names. This eliminates repetitive boilerplate when initializing configuration structs. The Authentication Service utilizes this pattern in /services/authentication_service/src/config.rs at line 7.
use macro_env_var::env_vars;
let Config {
api_key,
bucket_name,
region,
} = env_vars! {
API_KEY,
BUCKET_NAME,
REGION,
};
maybe_env_vars! for Bulk Optional Loading
Use maybe_env_vars! to load a set of optional variables into a struct where each field is Option<T>. The Native App Server employs this approach in /tooling/native_app_server/src/main.rs at line 4 to allow optional development defaults without failing when they are absent.
use macro_env_var::maybe_env_vars;
let Config {
log_level,
sentry_dsn,
} = maybe_env_vars! {
LOG_LEVEL,
SENTRY_DSN,
};
Legacy Function-Style Helpers
For older code paths, the crate also provides optional_read_env_var and maybe_read_env_var as function-style alternatives for single optional reads. These return Option<String> but lack the compile-time struct generation and validation guarantees of the newer macros.
Real-World Implementation Examples
The macro_env_var macros appear consistently across the repository, confirming the architectural standard is enforced in practice.
The Authentication Service initializes its configuration in /services/authentication_service/src/config.rs by importing both env_vars and maybe_env_vars macros to handle mixed required and optional settings in a single struct.
The Worker Trigger service follows the same idiom in /services/worker_trigger/src/config.rs at line 4, importing the macro-based loader to maintain consistency with the authentication service pattern.
For command-line utilities requiring strict guarantees, the Task Dedup crate uses env_var! directly in its binary entry point at /crates/task_dedup/src/bin/pull_task_corpus.rs line 48. This ensures required variables are present before the tool continues execution, preventing partial processing runs.
Even infrastructure helpers like the AWS Config utility at /crates/macro_aws_config/src/lib.rs line 6 employ maybe_env_var! to optionally read AWS credentials without failing when local environment variables are absent.
Summary
- All environment variables be accessed in Macro through the
macro_env_varcrate located at/crates/macro_env_var; direct usage ofstd::env::varis prohibited. - Four primary macros cover all use cases:
env_var!(required single),maybe_env_var!(optional single),env_vars!(required bulk), andmaybe_env_vars!(optional bulk). - Source enforcement appears at line 11 of
/crates/macro_env_var/src/lib.rs, which documents the crate as the sanctioned wrapper. - Service initialization occurs in dedicated
config.rsmodules, as seen in/services/authentication_service/src/config.rsand/services/worker_trigger/src/config.rs. - Legacy functions
optional_read_env_varandmaybe_read_env_varexist for older code but are superseded by the macro-based approach.
Frequently Asked Questions
Can I use std::env::var directly in the Macro codebase?
No. The source code at /crates/macro_env_var/src/lib.rs at line 11 explicitly prohibits direct usage of std::env::var or std::env::var_os. All environment variables be accessed in Macro through the sanctioned wrapper to ensure consistent security policies, centralized secret fetching, and uniform error handling.
How do I handle environment variables that might not be set?
Use the maybe_env_var! macro for individual optional variables, or maybe_env_vars! for bulk optional loading. Both return Option<String> (or Option<T> for parsed values), yielding None when variables are unset or empty. This pattern is implemented in /crates/macro_aws_config/src/lib.rs for optional AWS credential loading.
Where is the macro_env_var crate located in the repository?
The crate lives at /crates/macro_env_var in the repository root. The core macros are defined in /crates/macro_env_var/src/lib.rs, which includes the enforcement comment at line 11 stating this is the sanctioned wrapper around standard environment access.
Why does Macro enforce macros instead of functions for environment access?
The compile-time macros ensure variables are evaluated at service startup, enabling immediate failure for missing required configuration. This approach supports generating typed structs for bulk loading via env_vars! and maybe_env_vars!, and allows the test suite to override values without modifying the actual process environment, as demonstrated in the authentication and worker trigger services.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →