akka-hosting-actor-patterns
Patterns for building entity actors with Akka.Hosting - GenericChildPerEntityParent, message extractors, cluster sharding abstraction, akka-reminders, and ITimeProvider. Supports both local testing and clustered production modes.
By aaronontheweb · 382 installs
npx skills add aaronontheweb/dotnet-skills --skill akka-hosting-actor-patterns
Source repository · Upstream listing
Akka.Hosting Actor Patterns
When to Use This Skill
Use this skill when:
Building entity actors that represent domain objects (users, orders, invoices, etc.)
Need actors that work in both unit tests (no clustering) and production (cluster sharding)
Setting up scheduled tasks with akka reminders
Registering actors with Akka.Hosting extension methods
Creating reusable actor configuration patterns
Core Principles
1. Execution Mode Abstraction Same actor code runs locally (tests) or clustered (production)
2. GenericChildPerEntityParent for Local Mimics sharding semantics without cluster overhead
3. Message Extractors for Routing Reuse Akka.Cluster.Sharding's IMessageExtractor interface
4. Akka.Hosting Extension Methods Fluent configuration that composes well
5. ITimeProvider for Testability Use ActorSystem.Scheduler instead of DateTime.Now
Execution Modes
Define an enum to control actor behavior:
GenericChildPerEntityParent
A lightweight parent actor that routes messages to child entities, mimicking cluster sharding semantics without requiring a cluster:
Message Extractors
Create extractors that implement IMessageExtractor from Akka.Cluster.Sharding:
Akka.Hosting Extension Methods
Create extension methods that abstract the execution mode:
Composing Multiple Actors
Create a convenience method that registers all domain actors:
Using ITimeProvider for Scheduling
Register the ActorSystem's Scheduler as an ITimeProvider for testable time based logic:
Akka.Reminders Integration
For durable scheduled tasks that survive restarts, use akka reminders:
Custom Reminder Resolver for Child Per Entity
Route reminder callbacks to GenericChildPerEntityParent actors:
Singleton Actors (Not Sharded)
For actors that should only have one instance:
Marker Types for Registry
When you need to reference actors that are registered as parents:
DI Scope Management in Actors
Actors don't have automatic DI scopes. Unlike ASP.NET controllers (where each HTTP request creates a scope), actors are long lived. If you need scoped services (like DbContext ), inject IServiceProvider and create scopes manually.
Pattern: Scope Per Message
Why This Pattern
Benefit Explanation
Fresh DbContext per message No stale entity tracking between messages
Proper disposal Database connections released after each message
Isolation One message's errors don't corrupt another's state
Testable Can inject mock IServiceProvider in tests
Singleton Services Direct Injection
For stateless, thread safe services, inject directly (no scope needed):
Common Mistake: Injecting Scoped Services Directly
For more on DI lifetimes and scope management, see microsoft extensions/dependency injection skill.
Cluster Sharding Configuration
RememberEntities: Almost Always False
RememberEntities controls whether the shard region remembers and automatically restarts all entities that were ever created. This should almost always be false .
When RememberEntities = true causes problems:
Problem Explanation
Unbounded memory growth Every entity ever created gets remembered and restarted forever
Slow cluster startup Cluster must restart thousands/millions of entities on boot
Stale entity resurrection Expired sessions, sent emails, old orders all get restarted
No passivation Idle entities consume memory indefinitely (passivation is disabled)
When to Use Each Setting
Entity Type RememberEntities Reason
UserSessionActor false Sessions expire, created on login
DraftActor false Drafts are sent/discarded, ephemeral
EmailSenderActor false Fire and forget operations
OrderActor false Orders complete, new ones created constantly
ShoppingCartActor false Carts expire, abandoned carts common
TenantActor maybe true Fixed set of tenants, always needed
AccountActor maybe true Bounded set of accounts, long lived
Rule of thumb: Use RememberEntities = true only for:
1. Bounded entity sets (known upper limit)
2. Long lived domain entities that should always be available
3. Entities where the cost of remembering < cost of lazy creation
Marker Types with WithShardRegion<T
When using WithShardRegion<T , the generic parameter T serves as a marker type for the ActorRegistry . Use a dedicated marker type (not the actor class itself) for consistent registry access:
Why marker types?
WithShardRegion<T auto registers the shard region under type T
Using the actor class directly can cause confusion (registry returns region, not actor)
Marker types make the intent explicit and work consistently in both LocalTest and Clustered modes
Avoiding Redundant Registry Calls
WithShardRegion<T automatically registers the shard region in the ActorRegistry . Don't call registry.Register<T () again:
Best Practices
1. Always support both execution modes Makes testing easy without code changes
2. Use strongly typed IDs OrderId instead of string or Guid
3. Interface based message routing IWithOrderId for type safe extraction
4. Register parent, not children For child per entity, register the parent in ActorRegistry
5. Marker types for clarity Use empty marker classes for registry lookups
6. Composition over inheritance Chain extension methods, don't create deep hierarchies
7. ITimeProvider for scheduling Never use DateTime.Now directly in actors
8. akka reminders for durability Use for scheduled tasks that must survive restarts
9. RememberEntities = false by default Only set to true for bounded, long lived entities