AllFrame uses Cargo feature flags to provide modular compilation and flexible deployment options. This allows you to include only the features you need, reducing binary size and compilation time.
# Minimal build (MVP adapters only)
cargo build --no-default-features
# Default build (recommended for most projects)
cargo build
# Production build with all features
cargo build --all-features
# Custom feature selection
cargo build --no-default-features --features "di,router,cqrs"The following features are enabled by default:
default = ["di", "openapi", "router", "otel", "health"]di- Dependency Injection and Clean Architectureopenapi- OpenAPI schema generationrouter- Protocol-agnostic routing (REST, GraphQL, gRPC)otel- OpenTelemetry observabilityhealth- Health check server (requires hyper)
Note: cqrs is NOT in the default features. You must explicitly enable it if needed.
Enables: Dependency Injection container and Clean Architecture macros
Macros:
#[domain]- Domain layer (pure business logic)#[repository]- Repository layer (data access)#[use_case]- Use case layer (application logic)#[handler]- Handler layer (interface)
Example:
use allframe_core::arch::*;
#[domain]
struct User {
id: String,
email: String,
}
#[repository]
#[async_trait::async_trait]
trait UserRepository: Send + Sync {
async fn find(&self, id: &str) -> Option<User>;
}Binary Impact: +50KB (macros + runtime)
Enables: Automatic OpenAPI 3.0 schema generation from handlers
Macros:
#[api_handler]- Generates OpenAPI schema from function signature
Example:
use allframe_core::router::*;
#[api_handler(
path = "/users",
method = "GET",
summary = "List all users"
)]
async fn list_users() -> Vec<User> {
vec![]
}Binary Impact: +30KB (schema generation)
Enables: Configuration-based routing with REST, GraphQL, and gRPC support
APIs:
Router- Central routing coordinatorRestAdapter,GraphQLAdapter,GrpcAdapter- Protocol adaptersRouterConfig- TOML-based configuration
Example:
# router.toml
[server]
host = "0.0.0.0"
port = 3000
[rest]
enabled = true
prefix = "/api"
[graphql]
enabled = true
path = "/graphql"use allframe_core::router::*;
let config = RouterConfig::from_file("router.toml").await?;
let router = Router::from_config(config)?;Binary Impact: +100KB (router + config parsing)
Enables: HTTP health check server infrastructure
Dependencies: hyper, hyper-util
APIs:
HealthServer- HTTP server for health endpointsHealthChecktrait - Custom health check implementationHealthReport- Health status reportingDependency/DependencyStatus- Dependency health tracking
Example:
use allframe_core::health::{HealthServer, HealthReport, OverallStatus};
let server = HealthServer::new("0.0.0.0:8080");
server.start().await?;Binary Impact: +400KB (hyper + HTTP server)
Enables: Automatic distributed tracing, metrics, and context propagation
Macros:
#[traced]- Automatic span creation and tracing
APIs:
SpanRecorder- Test helper for span recordingMetricsRecorder- Test helper for metricsinject_context/extract_context- W3C Trace ContextExporterType- Configure exporters (Jaeger, OTLP, Stdout)
Example:
use allframe_core::otel::*;
#[traced]
async fn get_user(user_id: String) -> Result<User, String> {
// Automatically traced with span creation
}Binary Impact: +80KB (tracing infrastructure)
Enables: Complete OpenTelemetry SDK with OTLP exporter for production observability
Dependencies: otel, opentelemetry, opentelemetry_sdk, opentelemetry-otlp, tracing-opentelemetry, tracing-subscriber
Re-exports:
opentelemetry- Core OpenTelemetry APIopentelemetry_sdk- SDK configurationopentelemetry_otlp- OTLP exportertracing_opentelemetry- Tracing integrationtracing_subscriber- Log/trace configuration
Example:
use allframe_core::{opentelemetry, opentelemetry_sdk, tracing_subscriber};
use opentelemetry_sdk::trace::TracerProvider;
let tracer = opentelemetry_otlp::new_pipeline()
.tracing()
.with_exporter(opentelemetry_otlp::new_exporter().tonic())
.install_batch(opentelemetry_sdk::runtime::Tokio)?;Binary Impact: +300KB (full OTEL stack)
Status:
Enables: Command Query Responsibility Segregation and Event Sourcing patterns
Macros:
#[command]- Mark command structs#[query]- Mark query structs#[event]- Mark event enums#[command_handler]- Command handler functions#[query_handler]- Query handler functions
APIs:
EventStore<E>- Append-only event log (in-memory for MVP)Projectiontrait - Read model interfaceAggregatetrait - Event-sourced aggregate patternSagatrait - Multi-aggregate transaction coordinationCommandBus- Command dispatch (placeholder for MVP)QueryBus- Query dispatch
Example:
use allframe_core::cqrs::*;
#[derive(Clone)]
enum UserEvent {
Created { user_id: String, email: String },
EmailUpdated { new_email: String },
}
impl Event for UserEvent {}
let store = EventStore::new();
store.append("user-123", vec![
UserEvent::Created {
user_id: "user-123".to_string(),
email: "test@example.com".to_string(),
}
]).await?;Binary Impact: +150KB (event store + CQRS runtime)
Backend Options:
cqrs-sqlite- SQLite with WAL mode (recommended for offline/desktop)cqrs-allsource- AllSource embedded database (recommended for production)cqrs-postgres-⚠️ DEPRECATED - Usecqrs-allsourceinsteadcqrs-rocksdb- RocksDB embedded database backend
Enables: AllSource embedded database as the CQRS event store backend
Dependencies: allsource-core
Example:
use allframe_core::cqrs::{EventStore, AllSourceEventStore};
let store = AllSourceEventStore::new("event_store.db").await?;
store.append("aggregate-123", events).await?;Binary Impact: +50KB (AllSource runtime)
⚠️ DEPRECATED: AllSource v0.10.3 deprecated thepostgresfeature in favor of WAL-backed event-sourced repositories. Usecqrs-allsourceinstead. This feature flag will be removed in a future release.
Enables: PostgreSQL database as the CQRS event store backend
Dependencies: sqlx, PostgreSQL driver
Example:
use allframe_core::cqrs::{EventStore, PostgresEventStore};
let store = PostgresEventStore::connect("postgresql://...").await?;
store.append("aggregate-123", events).await?;Binary Impact: +500KB (PostgreSQL + SQLx)
Enables: RocksDB embedded database as the CQRS event store backend
Dependencies: rocksdb
Example:
use allframe_core::cqrs::{EventStore, RocksDbEventStore};
let store = RocksDbEventStore::open("event_store.db")?;
store.append("aggregate-123", events).await?;Binary Impact: +200KB (RocksDB)
Enables: SQLite database as the CQRS event store backend with WAL mode
Dependencies: rusqlite (bundled - statically links SQLite)
Example:
use allframe_core::cqrs::{EventStore, SqliteEventStoreBackend};
let backend = SqliteEventStoreBackend::new("events.db")?;
let store = EventStore::new(backend);
store.append("aggregate-123", events).await?;Binary Impact: +1MB (bundled SQLite)
Key Features:
- WAL mode for concurrent reads during writes
- Zero network dependencies
- Atomic appends via transactions
flush()for WAL checkpointing
Enables: Complete offline-first stack (implies cqrs + cqrs-sqlite + di + security)
Example:
allframe-core = { version = "0.1", features = ["offline"] }What you get:
- SQLite event store backend
- Compile-time DI with lazy initialization
- Security utilities for credential handling
- CQRS + Event Sourcing
Binary Impact: +1.5MB
Verified: Zero network dependencies (reqwest, redis, tonic, hyper are all excluded). Enforced by CI.
Enables: Vector similarity search via AllSource's fastembed + HNSW index
Dependencies: allsource-core/vector-search (fastembed, instant-distance)
Example:
use allframe_core::cqrs::AllSourceEventStore;
// With vector-search enabled, AllSource provides HNSW-based similarity search
// for embeddings generated via fastembed
let store = AllSourceEventStore::new("store.db").await?;
// Use AllSource's vector search APIs for semantic queriesBinary Impact: +5MB (fastembed model + HNSW index)
Enables: BM25 full-text keyword search via AllSource's tantivy integration
Dependencies: allsource-core/keyword-search (tantivy)
Example:
use allframe_core::cqrs::AllSourceEventStore;
// With keyword-search enabled, AllSource provides BM25 full-text search
// via tantivy for keyword-based queries
let store = AllSourceEventStore::new("store.db").await?;
// Use AllSource's keyword search APIs for text queriesBinary Impact: +2MB (tantivy)
Status: 🚧 Placeholder - Not yet implemented
Future: Integration with Claude Desktop and AI tools
Binary Impact: TBD
Enables: Re-exports reqwest for making HTTP requests
Dependencies: reqwest (with json and rustls-tls features)
Example:
use allframe_core::reqwest;
async fn fetch_data() -> Result<String, reqwest::Error> {
let response = reqwest::get("https://api.example.com/data").await?;
response.text().await
}Binary Impact: +500KB (reqwest + TLS)
Enables: Full GraphQL implementation using async-graphql
Dependencies: async-graphql, async-graphql-parser
APIs:
GraphQLProductionAdapter- Full GraphQL server- Schema introspection
- GraphiQL interface
Binary Impact: +800KB (async-graphql + dependencies)
Enables: Full gRPC implementation using tonic
Dependencies: tonic, prost, prost-types, tonic-reflection, tonic-health, tonic-build, tokio-stream, futures
APIs:
GrpcProductionAdapter- Full gRPC server- Protobuf code generation
- Service reflection
- Health checking
Binary Impact: +1.2MB (tonic + protobuf)
Enables: TLS/mTLS support for gRPC servers and clients
Dependencies: router-grpc, tonic/tls-ring, tonic/tls-native-roots, rustls-pemfile, tokio-rustls
Example:
use allframe_core::grpc::{GrpcServerBuilder, TlsConfig};
let tls_config = TlsConfig::new(
include_bytes!("server.crt"),
include_bytes!("server.key"),
);
let server = GrpcServerBuilder::new()
.with_tls(tls_config)
.build()?;Binary Impact: +200KB (TLS libraries)
Enables: Both router-graphql and router-grpc
Binary Impact: +2.0MB (combined)
Enables: Prometheus metrics collection and exposition
Dependencies: prometheus
Re-exports: prometheus crate
Example:
use allframe_core::prometheus::{Counter, Opts, Registry};
let counter = Counter::with_opts(Opts::new("requests_total", "Total requests"))?;
let registry = Registry::new();
registry.register(Box::new(counter.clone()))?;
counter.inc();Binary Impact: +100KB (prometheus)
Enables: High-performance in-memory caching with moka and concurrent maps with dashmap
Dependencies: moka (with future feature), dashmap
Re-exports:
moka- High-performance bounded cachedashmap- Concurrent HashMap
Example:
use allframe_core::moka::future::Cache;
use allframe_core::dashmap::DashMap;
// Moka cache with TTL
let cache: Cache<String, String> = Cache::builder()
.max_capacity(10_000)
.time_to_live(std::time::Duration::from_secs(300))
.build();
// DashMap for concurrent access
let map: DashMap<String, i32> = DashMap::new();
map.insert("key".to_string(), 42);Binary Impact: +150KB (moka + dashmap)
Enables: Redis client for distributed caching
Dependencies: redis (with tokio-comp and connection-manager features)
Re-exports: redis crate
Example:
use allframe_core::redis::{Client, AsyncCommands};
let client = Client::open("redis://127.0.0.1/")?;
let mut con = client.get_multiplexed_async_connection().await?;
con.set("my_key", "my_value").await?;
let value: String = con.get("my_key").await?;Binary Impact: +200KB (redis client)
Enables: Token bucket rate limiting with governor
Dependencies: governor
Re-exports: governor crate
Example:
use allframe_core::governor::{Quota, RateLimiter};
use std::num::NonZeroU32;
let limiter = RateLimiter::direct(Quota::per_second(NonZeroU32::new(10).unwrap()));
if limiter.check().is_ok() {
// Request allowed
} else {
// Rate limited
}Binary Impact: +80KB (governor)
Enables: Production-ready retry, circuit breaker, and rate limiting patterns
Dependencies: allframe-macros, backoff, governor, dashmap, parking_lot, rand
Macros:
#[retry(max_retries = 3)]- Wrap async functions with exponential backoff#[circuit_breaker(failure_threshold = 5)]- Fail-fast pattern for functions#[rate_limited(rps = 100, burst = 10)]- Token bucket rate limiting
APIs:
RetryConfig- Configurable retry behavior (max_retries, intervals, randomization)RetryExecutor- Async retry execution with exponential backoffRetryPolicytrait - Custom retry decision logicRetryBudget- System-wide retry token management (prevents retry storms)AdaptiveRetry- Adjusts retry behavior based on success/failure ratesRateLimiter- Token bucket rate limiting with burst supportAdaptiveRateLimiter- Backs off when receiving external 429 responsesKeyedRateLimiter<K>- Per-key rate limiting (per-endpoint, per-user)CircuitBreaker- Fail-fast pattern with Closed/Open/HalfOpen statesCircuitBreakerConfig- Configurable thresholds and timeoutsCircuitBreakerManager- Manages multiple circuit breakers by name
Example (Retry):
use allframe_core::resilience::{RetryConfig, RetryExecutor};
use std::time::Duration;
let config = RetryConfig::new(3)
.with_initial_interval(Duration::from_millis(100))
.with_max_interval(Duration::from_secs(5))
.with_multiplier(2.0);
let executor = RetryExecutor::new(config);
let result = executor.execute("fetch_data", || async {
// Fallible operation
Ok::<_, std::io::Error>("success")
}).await;Example (Circuit Breaker):
use allframe_core::resilience::{CircuitBreaker, CircuitBreakerConfig};
use std::time::Duration;
let config = CircuitBreakerConfig::new(5)
.with_success_threshold(2)
.with_timeout(Duration::from_secs(30));
let cb = CircuitBreaker::new("payment_service", config);
let result = cb.call(|| async { fetch_from_service().await }).await;Example (Rate Limiting):
use allframe_core::resilience::{RateLimiter, KeyedRateLimiter};
// Simple rate limiter: 100 requests/second, burst of 10
let limiter = RateLimiter::new(100, 10);
if limiter.check().is_ok() {
// Request allowed
}
// Per-endpoint rate limiting
let keyed: KeyedRateLimiter<&str> = KeyedRateLimiter::new(10, 5);
keyed.set_limit("premium_api", 100, 20); // Higher limit for premiumExample (Attribute Macros):
use allframe_core::{retry, circuit_breaker, rate_limited};
#[retry(max_retries = 3, initial_interval_ms = 100)]
async fn fetch_user(id: &str) -> Result<User, Error> {
// Automatically retried with exponential backoff
api.get_user(id).await
}
#[circuit_breaker(failure_threshold = 5, timeout_secs = 30)]
async fn call_payment_service() -> Result<Payment, Error> {
// Fails fast when circuit is open
payment_api.process().await
}
#[rate_limited(rps = 100, burst = 10)]
async fn handle_request() -> Response {
// Rate limited to 100 requests/second
process_request().await
}Binary Impact: +120KB (resilience patterns + dependencies)
Enables: Safe logging utilities for sensitive data obfuscation
Dependencies: allframe-macros, url
Macros:
#[derive(Obfuscate)]- Auto-generate safe Debug/Display with#[sensitive]field attribute
APIs:
obfuscate_url(url)- Strips credentials, path, and query from URLsobfuscate_redis_url(url)- Preserves host/port, hides authobfuscate_api_key(key)- Shows prefix/suffix only (e.g., "sk_l***mnop")obfuscate_header(name, value)- Smart header obfuscation (Authorization, Cookie, etc.)Obfuscatetrait - Custom obfuscation for user typesSensitive<T>wrapper - Debug/Display always shows "***"
Example (Obfuscation Functions):
use allframe_core::security::{obfuscate_url, obfuscate_api_key, obfuscate_header};
let url = "https://user:pass@api.example.com/v1/users?token=secret";
println!("Safe: {}", obfuscate_url(url));
// Output: "https://api.example.com/***"
let key = "sk_live_1234567890abcdef";
println!("Key: {}", obfuscate_api_key(key));
// Output: "sk_l***cdef"
let auth_header = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.secret";
println!("Auth: {}", obfuscate_header("Authorization", auth_header));
// Output: "Bearer ***"Example (Sensitive Wrapper):
use allframe_core::security::Sensitive;
let password = Sensitive::new("super_secret");
println!("{:?}", password); // Output: Sensitive(***)
println!("{}", password); // Output: ***
// Access the inner value when needed
let actual = password.as_inner();Example (Derive Macro):
use allframe_core::Obfuscate;
use allframe_core::security::Obfuscate as ObfuscateTrait;
#[derive(Obfuscate)]
struct DatabaseConfig {
host: String,
port: u16,
#[sensitive]
username: String,
#[sensitive]
password: String,
}
let config = DatabaseConfig {
host: "db.example.com".to_string(),
port: 5432,
username: "admin".to_string(),
password: "secret123".to_string(),
};
// Safe for logging!
println!("Connecting to: {}", config.obfuscate());
// Output: DatabaseConfig { host: "db.example.com", port: 5432, username: ***, password: *** }Binary Impact: +30KB (url parsing + obfuscation)
Enables: Common utility crates for date/time, URLs, synchronization, and random numbers
Dependencies: chrono, url, parking_lot, rand
Re-exports:
chrono- Date and time handling (with serde support)url- URL parsing and manipulationparking_lot- Efficient synchronization primitives (Mutex, RwLock)rand- Random number generation
Example:
use allframe_core::{chrono, url, parking_lot, rand};
use chrono::{DateTime, Utc};
use url::Url;
use parking_lot::Mutex;
use rand::Rng;
let now: DateTime<Utc> = Utc::now();
let api_url = Url::parse("https://api.example.com")?;
let counter = Mutex::new(0);
let random: u32 = rand::thread_rng().gen();Binary Impact: +200KB (combined utilities)
cargo build --no-default-featuresSize: ~800KB Features: Basic router with MVP adapters only Use case: Prototypes, learning, embedded systems
cargo buildSize: ~1.1MB Features: DI, OpenAPI, Router, OTEL Use case: Most applications
cargo build --features cqrsSize: ~1.3MB Features: Default + CQRS/Event Sourcing Use case: Event-sourced systems, audit logging
cargo build --features routerSize: ~1.1MB Features: Default configuration Use case: REST APIs
cargo build --features router-graphqlSize: ~1.9MB Features: Default + Production GraphQL Use case: GraphQL APIs
cargo build --features router-grpcSize: ~2.3MB Features: Default + Production gRPC Use case: Microservices, high-performance APIs
cargo build --all-featuresSize: ~3.3MB Features: Everything enabled Use case: Enterprise applications, maximum flexibility
cargo build --features "cache-memory,cache-redis"Features: Default + Memory + Redis caching Use case: High-traffic APIs requiring caching layer
cargo build --features "router-grpc,router-grpc-tls,rate-limit,resilience,metrics"Features: gRPC + TLS + Rate limiting + Retry patterns + Prometheus metrics Use case: Production microservices with full resilience
cargo build --features "otel-otlp,metrics"Features: Full OpenTelemetry + Prometheus Use case: Services requiring comprehensive observability
di
└─ allframe-macros
openapi
└─ (no dependencies)
health
├─ hyper
└─ hyper-util
router
└─ toml (for config parsing)
router-graphql
├─ router
├─ async-graphql
└─ async-graphql-parser
router-grpc
├─ router
├─ tonic
├─ prost
├─ prost-types
├─ tonic-build
├─ tonic-reflection
├─ tonic-health
├─ tokio-stream
└─ futures
router-grpc-tls
├─ router-grpc
├─ tonic/tls-ring
├─ tonic/tls-native-roots
├─ rustls-pemfile
└─ tokio-rustls
router-full
├─ router-graphql
└─ router-grpc
cqrs
└─ (no dependencies)
cqrs-allsource
├─ cqrs
└─ allsource-core
cqrs-postgres
├─ cqrs
└─ sqlx (postgres)
cqrs-rocksdb
├─ cqrs
└─ rocksdb
otel
├─ allframe-macros
└─ tracing
otel-otlp
├─ otel
├─ opentelemetry
├─ opentelemetry_sdk
├─ opentelemetry-otlp
├─ tracing-opentelemetry
└─ tracing-subscriber
http-client
└─ reqwest (json, rustls-tls)
metrics
└─ prometheus
cache-memory
├─ moka (future)
└─ dashmap
cache-redis
└─ redis (tokio-comp, connection-manager)
rate-limit
└─ governor
resilience
├─ allframe-macros
├─ backoff (tokio)
├─ governor
├─ dashmap
├─ parking_lot
└─ rand
security
├─ allframe-macros
└─ url
utils
├─ chrono (serde)
├─ url
├─ parking_lot
└─ rand
cqrs
└─ allframe-macros
cqrs-allsource
├─ cqrs
└─ allsource-core
cqrs-postgres
├─ cqrs-allsource
└─ allsource-core/postgres
cqrs-rocksdb
├─ cqrs-allsource
└─ allsource-core/rocksdb-storage
vector-search
├─ cqrs-allsource
└─ allsource-core/vector-search (fastembed, instant-distance)
keyword-search
├─ cqrs-allsource
└─ allsource-core/keyword-search (tantivy)
cargo testcargo test --no-default-features --features "di,router"cargo test --features cqrscargo test --all-featurescargo test --features cqrs --test 06_cqrs_commands[dependencies]
allframe = "0.1" # Uses default features
# Or customize:
allframe = { version = "0.1", default-features = false, features = ["di", "router"] }
# Enable CQRS:
allframe = { version = "0.1", features = ["cqrs"] }
# Production GraphQL:
allframe = { version = "0.1", features = ["router-graphql"] }
# Everything:
allframe = { version = "0.1", features = ["cqrs", "router-full"] }| Configuration | Unoptimized | Optimized (--release) |
|---|---|---|
| Minimal (no features) | ~800 KB | ~400 KB |
| Default | ~1.1 MB | ~550 KB |
| + CQRS | ~1.3 MB | ~650 KB |
| + router-graphql | ~1.9 MB | ~950 KB |
| + router-grpc | ~2.3 MB | ~1.1 MB |
| All features | ~3.3 MB | ~1.6 MB |
Note: Sizes are approximate and may vary based on platform and Rust version
allframe = { version = "0.1", default-features = false, features = ["router"] }allframe = { version = "0.1", features = [] } # Use defaultsallframe = { version = "0.1", features = ["router-graphql"] }allframe = { version = "0.1", features = ["router-grpc"] }allframe = { version = "0.1", features = ["cqrs"] }allframe = { version = "0.1", features = ["cqrs", "router-full"] }A: CQRS adds 150KB to binary size and is only needed for event-sourced systems. Most applications don't need it, so we keep it optional to reduce default binary size.
A: Yes! Use:
cargo build --no-default-features --features cqrsA: router provides configuration-based routing with MVP adapters. router-graphql adds the full async-graphql library for production GraphQL support.
A: No, you can disable it:
cargo build --no-default-features --features "di,openapi,router"A: Absolutely! Use:
cargo build --features "cqrs,router-graphql"cqrs-sqlite- SQLite persistence for CQRSmcp- Model Context Protocol integration (separate crate available)auth- Authentication/authorization helperswebsockets- WebSocket support
- CQRS + AllSource Assessment
- Milestone 0.4 Complete
- Main README.md