| Pattern | Consistency | Scale | Complexity | Suitable For |
|---|---|---|---|---|
| Pessimistic Locking | Strong | Low | Low | Monoliths, legacy systems |
| Saga Pattern | Eventual | High | High | Microservices |
| CQRS | Eventual | High | High | Read-heavy systems, DDD |
| Mediator | Depends | Med | Medium | Coordinated command handling |
| Event Sourcing | Eventual | High | High | Auditable systems |
| Two-Phase Commit | Strong | Low | High | Cross-DB transactional ops |
| Outbox Pattern | Eventual | High | Medium | DB + messaging consistency |
Two powerful transaction patterns for modern applications: AtomicService for ACID transactions and SagaPatternService for distributed transactions with eventual consistency.
This library offers two complementary approaches to handle transactions in both monolithic and distributed architectures:
| Pattern | Use Case | Consistency | Scope | Recovery |
|---|---|---|---|---|
| AtomicService | Single service/database | Immediate (ACID) | Local operations | Transaction rollback |
| SagaPatternService | Multiple services | Eventual | Distributed operations | Compensating actions |
- Hierarchical Transactions - Parent-child transaction support
- Enhanced Retry Logic - Configurable retry with exponential backoff
- Performance Monitoring - Built-in metrics and correlation tracking
- Multiple Isolation Levels - ReadCommitted, RepeatableRead, Serializable
- Deadlock Detection - Smart handling of transient database errors
- Flexible Configuration - Per-operation timeouts and retry policies
- Compensating Actions - Automatic rollback through compensation
- State Persistence - Durable saga state with resume capability
- Step Orchestration - Sequential, conditional, and parallel execution
- Error Recovery - Comprehensive error handling and retry strategies
- Monitoring & Observability - Full saga lifecycle tracking
- Integration Ready - Works seamlessly with AtomicService
// Program.cs
using Persistence.Database;
var builder = WebApplication.CreateBuilder(args);
// Configure AtomicService
builder.Services.Configure<AtomicServiceOptions>(options =>
{
options.MaxRetryAttempts = 3;
options.TransactionTimeout = TimeSpan.FromMinutes(5);
options.DefaultIsolationLevel = IsolationLevel.ReadCommitted;
});
// Configure SagaPatternService
builder.Services.Configure<SagaPatternOptions>(options =>
{
options.StepTimeout = TimeSpan.FromMinutes(5);
options.MaxRetryAttempts = 3;
options.EnableStateLogging = true;
});
// Register services
builder.Services.AddScoped<IAtomicService, AtomicService>();
builder.Services.AddScoped<ISagaStateStore, InMemorySagaStateStore>();
builder.Services.AddScoped<ISagaPatternService, SagaPatternService>();
var app = builder.Build();public class OrderService
{
private readonly IAtomicService _atomicService;
// Simple atomic operation
public async Task CreateOrderAsync(Order order)
{
await _atomicService.ExecuteAtomicallyAsync(async () =>
{
await _orderRepository.CreateAsync(order);
await _auditRepository.LogAsync(order.Id, "OrderCreated");
await _notificationService.SendConfirmationAsync(order.CustomerId);
});
}
// Parent-child hierarchical transaction
public async Task ProcessComplexOrderAsync(Order order)
{
await _atomicService.ExecuteAsParentAsync(async () =>
{
await CreateOrderAsync(order); // Child transaction
await _paymentService.ProcessPaymentAsync(order.Payment); // Child transaction
await _inventoryService.ReserveItemsAsync(order.Items); // Child transaction
});
}
// With custom options
public async Task ProcessCriticalOrderAsync(Order order)
{
var options = new AtomicOperationOptions
{
OperationName = "CriticalOrderProcessing",
IsolationLevel = IsolationLevel.Serializable,
Timeout = TimeSpan.FromMinutes(10),
MaxRetryAttempts = 5
};
await _atomicService.ExecuteAtomicallyAsync(async () =>
{
// Critical business logic here
}, options);
}
}public class DistributedOrderService
{
private readonly ISagaPatternService _sagaService;
public async Task<SagaExecutionResult> ProcessDistributedOrderAsync(OrderRequest request)
{
var context = new OrderSagaContext(request);
var steps = new List<ISagaStep<OrderSagaContext>>
{
// Step 1: Process Payment
SagaStepBuilder.Create<OrderSagaContext>(
"ProcessPayment", 1,
executeAction: async (ctx, ct) =>
{
var payment = await _paymentService.ChargeAsync(ctx.OrderRequest.Payment);
ctx.PaymentId = payment.Id;
return StepResult.Success;
},
compensateAction: async (ctx, ct) =>
{
if (!string.IsNullOrEmpty(ctx.PaymentId))
{
await _paymentService.RefundAsync(ctx.PaymentId);
}
return StepResult.Success;
}
),
// Step 2: Reserve Inventory
SagaStepBuilder.Create<OrderSagaContext>(
"ReserveInventory", 2,
executeAction: async (ctx, ct) =>
{
var reservation = await _inventoryService.ReserveAsync(ctx.OrderRequest.Items);
ctx.ReservationId = reservation.Id;
return StepResult.Success;
},
compensateAction: async (ctx, ct) =>
{
if (!string.IsNullOrEmpty(ctx.ReservationId))
{
await _inventoryService.ReleaseAsync(ctx.ReservationId);
}
return StepResult.Success;
}
),
// Step 3: Schedule Shipping
SagaStepBuilder.Create<OrderSagaContext>(
"ScheduleShipping", 3,
executeAction: async (ctx, ct) =>
{
var shipping = await _shippingService.ScheduleAsync(ctx.OrderRequest);
ctx.Data["ShippingId"] = shipping.Id;
return StepResult.Success;
},
compensateAction: async (ctx, ct) =>
{
if (ctx.Data.TryGetValue("ShippingId", out var shippingId))
{
await _shippingService.CancelAsync(shippingId.ToString()!);
}
return StepResult.Success;
}
)
};
return await _sagaService.ExecuteSagaAsync(context, steps);
}
}public class HybridOrderService
{
public async Task<StepResult> ProcessOrderDataAsync(OrderContext context, CancellationToken ct)
{
// Use AtomicService for local consistency within saga steps
await _atomicService.ExecuteAtomicallyAsync(async () =>
{
// Local ACID operations within the distributed saga step
await _orderRepository.CreateAsync(context.Order);
await _auditRepository.LogAsync(context.Order.Id, "OrderCreated");
await _customerRepository.UpdateOrderCountAsync(context.Order.CustomerId);
}, new AtomicOperationOptions
{
OperationName = "SagaStep.LocalOrderData",
CorrelationData = new Dictionary<string, object>
{
["SagaId"] = context.SagaId,
["OrderId"] = context.Order.Id
}
});
return StepResult.Success;
}
}- β Single service operations - All operations within one service/database
- β Need immediate consistency - ACID properties required
- β Traditional database transactions - Relational database operations
- β Parent-child service relationships - Hierarchical transaction coordination
- β Short-lived operations - Transactions that complete quickly
- β Multiple microservices involved - Cross-service coordination needed
- β External API integrations - Third-party services in the flow
- β Long-running business processes - Operations that take significant time
- β Need eventual consistency - Can tolerate temporary inconsistency
- β Distributed architecture - Services across different databases/systems
- π Each saga step needs local ACID guarantees - Best of both worlds
- π Distributed coordination with local consistency - Hybrid approach
- π Complex business processes - Spanning multiple services with local data integrity
graph TB
A[Client Request] --> B{Transaction Type?}
B -->|Local Operations| C[AtomicService]
B -->|Distributed Operations| D[SagaPatternService]
B -->|Hybrid| E[Both Services]
C --> C1[Transaction Scope]
C --> C2[Retry Logic]
C --> C3[Performance Monitoring]
D --> D1[Saga Steps]
D --> D2[Compensation Actions]
D --> D3[State Persistence]
E --> E1[Saga Orchestration]
E1 --> E2[Step 1: AtomicService]
E1 --> E3[Step 2: AtomicService]
E1 --> E4[Step N: AtomicService]
C1 --> F[Database]
D3 --> G[Saga State Store]
E2 --> F
E3 --> F
E4 --> F
| Pattern | Latency | Throughput | Consistency | Complexity | Scalability |
|---|---|---|---|---|---|
| AtomicService | Low | High | Strong | Low | Vertical |
| SagaPattern | Medium | Medium | Eventual | Medium | Horizontal |
| Hybrid | Medium | High | Mixed | High | Both |
- AtomicService Usage Guide - Comprehensive guide for ACID transactions
- Saga Pattern Usage Guide - Complete saga implementation guide
- API Reference - Full API documentation
- Configuration Guide - Setup and configuration options
- E-commerce Order Processing - Real-world e-commerce example
- Banking Transfers - Financial transaction examples
- Microservices Integration - Cross-service coordination
- Performance Optimization - High-throughput scenarios
- Error Handling Strategies - Comprehensive error management
- Monitoring & Observability - Metrics and logging
- Testing Strategies - Unit and integration testing
- Production Deployment - Production considerations
public class AtomicServiceOptions
{
public int MaxRetryAttempts { get; set; } = 3;
public TimeSpan BaseRetryDelay { get; set; } = TimeSpan.FromMilliseconds(100);
public TimeSpan TransactionTimeout { get; set; } = TimeSpan.FromMinutes(5);
public IsolationLevel DefaultIsolationLevel { get; set; } = IsolationLevel.ReadCommitted;
public bool EnablePerformanceLogging { get; set; } = true;
public bool EnableDistributedTransactions { get; set; } = false;
}public class SagaPatternOptions
{
public TimeSpan StepTimeout { get; set; } = TimeSpan.FromMinutes(5);
public TimeSpan CompensationTimeout { get; set; } = TimeSpan.FromMinutes(10);
public int MaxRetryAttempts { get; set; } = 3;
public TimeSpan RetryDelay { get; set; } = TimeSpan.FromSeconds(1);
public bool EnableStateLogging { get; set; } = true;
public bool EnableCompensationLogging { get; set; } = true;
}Both services provide comprehensive monitoring capabilities:
- Transaction success/failure rates
- Operation duration and performance
- Retry attempt tracking
- Compensation execution monitoring
- Resource usage statistics
- Structured logging with correlation IDs
- Performance logging for optimization
- Error tracking with context
- Saga state change events
// Built-in health checks
services.AddHealthChecks()
.AddCheck<AtomicServiceHealthCheck>("atomic-service")
.AddCheck<SagaPatternHealthCheck>("saga-pattern");[Test]
public async Task AtomicService_Should_Rollback_On_Exception()
{
// Arrange
var mockRepository = new Mock<IRepository>();
mockRepository.Setup(x => x.SaveAsync(It.IsAny<Entity>()))
.ThrowsAsync(new InvalidOperationException());
// Act & Assert
await Assert.ThrowsAsync<InvalidOperationException>(() =>
_atomicService.ExecuteAtomicallyAsync(async () =>
{
await mockRepository.Object.SaveAsync(new Entity());
}));
// Verify rollback occurred
mockRepository.Verify(x => x.SaveAsync(It.IsAny<Entity>()), Times.Once);
}[Test]
public async Task SagaPattern_Should_Compensate_On_Step_Failure()
{
// Arrange
var context = new TestSagaContext();
var steps = CreateTestStepsWithFailure();
// Act
var result = await _sagaService.ExecuteSagaAsync(context, steps);
// Assert
Assert.That(result.FinalStatus, Is.EqualTo(SagaStatus.Compensated));
Assert.That(context.CompensatedSteps.Count, Is.GreaterThan(0));
}