Why Choose Foundatio?
Foundatio was born from real-world experience building large-scale cloud applications. Here's why it stands out from other approaches.
The Problem
When building distributed applications, you typically face these challenges:
- Vendor Lock-in: Direct use of Redis, Azure, or AWS SDKs couples your code to specific providers
- Testing Complexity: External dependencies make testing slow and unreliable
- Development Setup: Developers need to run Redis, Azure Storage Emulator, etc. locally
- Inconsistent Patterns: Different team members use different approaches for the same problems
- Reinventing the Wheel: Every project implements caching, queuing, locking from scratch
The Foundatio Solution
🔌 Pluggable Abstractions
Write your code against interfaces, not implementations:
// Your service doesn't care about the implementation
public class OrderProcessor
{
private readonly ICacheClient _cache;
private readonly IQueue<Order> _queue;
public OrderProcessor(ICacheClient cache, IQueue<Order> queue)
{
_cache = cache;
_queue = queue;
}
}Change from in-memory to Redis with one line in your DI configuration:
// Development
services.AddSingleton<ICacheClient, InMemoryCacheClient>();
// Production
services.AddSingleton<ICacheClient>(sp =>
new RedisCacheClient(o => o.ConnectionMultiplexer = redis));🧪 Superior Testing Experience
No mocking frameworks needed - use real implementations:
[Fact]
public async Task Should_Process_Order_With_Caching()
{
// Arrange - use in-memory implementations
var cache = new InMemoryCacheClient();
var queue = new InMemoryQueue<Order>();
var processor = new OrderProcessor(cache, queue);
// Act
await processor.ProcessAsync(new Order { Id = 1 });
// Assert
var cached = await cache.GetAsync<Order>("order:1");
Assert.NotNull(cached);
}Benefits:
- Fast: No network calls
- Isolated: No shared state between tests
- Reliable: No external service failures
- Complete: Test the exact code path used in production
🚀 Zero-Config Development
Start coding immediately without external dependencies:
// Works out of the box - no Redis, no Azure, no AWS
var cache = new InMemoryCacheClient();
var queue = new InMemoryQueue<WorkItem>();
var messageBus = new InMemoryMessageBus();
var storage = new InMemoryFileStorage();Compare to other approaches:
- Direct Redis: Requires running Redis server
- Direct Azure: Requires Azure subscription or emulator
- Direct AWS: Requires AWS account or LocalStack
📊 Comparison with Alternatives
vs. Direct SDK Usage
| Aspect | Direct SDK | Foundatio |
|---|---|---|
| Testing | Mock everything | Use in-memory implementations |
| Switching providers | Rewrite code | Change DI registration |
| Local development | Run services | Zero dependencies |
| Learning curve | Learn each SDK | Learn one API |
vs. Building Your Own
| Aspect | DIY | Foundatio |
|---|---|---|
| Time to implement | Weeks/months | Minutes |
| Battle tested | No | Yes (years of production use) |
| Edge cases handled | Maybe | Comprehensive |
| Maintenance burden | On you | On community |
vs. Other Libraries
Foundatio is unique in providing:
- Complete abstraction set: Caching, Queues, Locks, Messaging, Storage, Jobs, Resilience
- Consistent API design: Same patterns across all abstractions
- In-memory implementations: For all abstractions, not just some
- Active maintenance: Regular updates and community support
Real-World Usage
Exceptionless
Exceptionless, a large-scale error tracking application, uses Foundatio extensively:
- Caching: User sessions, resolved geo-locations with
MaxItemslimit - Queues: Event processing pipeline
- Jobs: Background processing for reports, cleanup, notifications
- Storage: Error stack traces, attachments
- Messaging: Real-time notifications
Enterprise Applications
Teams choose Foundatio for:
- Consistency: Same patterns across all services
- Onboarding: New developers learn one API
- Migration: Easy to switch providers without code changes
- Testing: Comprehensive test coverage without infrastructure
Feature Highlights
Hybrid Caching
Combine local and distributed caching for maximum performance:
var hybridCache = new HybridCacheClient(
distributedCache: new RedisCacheClient(...),
messageBus: new RedisMessageBus(...)
);- Local cache for fastest access
- Distributed cache for consistency
- Message bus for cache invalidation
Scoped Caching
Easily namespace your cache keys:
var scopedCache = new ScopedCacheClient(cache, "tenant:123");
await scopedCache.SetAsync("user", user); // Key: "tenant:123:user"
await scopedCache.RemoveByPrefixAsync(""); // Clears all tenant:123 keysThrottling Locks
Rate limit operations across all instances:
var throttledLocker = new ThrottlingLockProvider(
cache,
maxHits: 10,
period: TimeSpan.FromMinutes(1)
);
// Only allows 10 operations per minute across all instances
if (await throttledLocker.AcquireAsync("api-call"))
{
await CallExternalApiAsync();
}Queue Behaviors
Extend queue functionality with behaviors:
queue.AttachBehavior(new MetricsQueueBehavior<T>(metrics));
queue.AttachBehavior(new RetryQueueBehavior<T>(maxRetries: 3));Resilience Policies
Built-in retry and circuit breaker:
var policy = new ResiliencePolicyBuilder()
.WithMaxAttempts(5)
.WithExponentialDelay(TimeSpan.FromSeconds(1))
.WithMaxDelay(TimeSpan.FromMinutes(1))
.WithJitter()
.WithCircuitBreaker(cb => cb
.WithFailureRatio(0.5)
.WithBreakDuration(TimeSpan.FromMinutes(1)))
.Build();Getting Started
Ready to try Foundatio?
- Installation & Setup - Get running in minutes
- Caching Guide - Deep dive into caching
- Sample Application - See complete examples
The combination of consistent abstractions, excellent testability, and production-ready implementations makes Foundatio an excellent choice for modern .NET applications.