Actor Model
debt(d8/e8/b9/t6)
Closest to 'silent in production until users hit it' (d9), -1. The term's detection_hints explicitly state automated detection is not possible. Misuses like shared state between actors, hidden deadlocks from synchronous call chains, or missing supervision trees cannot be caught by any standard tooling — they manifest as subtle runtime failures (deadlocks, message loss, cascading crashes). Only careful code review or load/chaos testing reveals these issues, but some problems (like deadlocks under specific message orderings) may only appear in production under load.
Closest to 'architectural rework' (e9), -1. The quick_fix says 'keep actor state private, communicate only via messages, implement supervision, avoid synchronous blocking calls' — but correcting a misuse like shared state between actors or tight synchronous coupling requires rethinking the communication topology and potentially redesigning the entire actor hierarchy. Missing supervision trees require introducing a fault-tolerance strategy across the system. These are cross-cutting architectural concerns, not localized fixes. However, it's not always a full rewrite — an experienced team can incrementally refactor actor boundaries — hence e8 rather than e9.
Closest to 'defines the system's shape' (b9). The actor model is an architectural paradigm that fundamentally shapes how the entire system is structured. Every component, communication path, error handling strategy, and deployment topology is determined by this choice. It applies to cli and queue-worker contexts and is tagged as distributed/concurrency — meaning it's load-bearing across the entire system. Once adopted, the actor model becomes the gravitational center of the codebase; migrating away is essentially a rewrite.
Closest to 'serious trap' (t7), -1. The misconception states that 'Actor model eliminates all concurrency bugs' — this is a significant trap because developers coming from shared-memory concurrency expect that adopting actors means concurrency problems disappear. In reality, message ordering isn't guaranteed between actors, actors can deadlock via synchronous request-response chains, and missing supervision means failures cascade. The common mistakes (sharing state, synchronous coupling, no supervision) all stem from misunderstanding what the model actually guarantees. It's not quite t7 because the traps are well-documented in the Erlang/Elixir ecosystem and most practitioners eventually learn them, but they genuinely contradict the 'actors solve everything' intuition.
TL;DR
Explanation
Actor: unit of computation with private state, a mailbox, and behaviour. Actors communicate only by sending messages — no shared memory. On receiving a message, an actor can: send messages to other actors, create new actors, change its next behaviour. Benefits: no race conditions (no shared state), location transparency (actor can be remote), fault tolerance (supervisors restart failed actors). Implementations: Erlang/OTP (pioneered it), Akka (JVM), Elixir, Microsoft Orleans. PHP: not native but Amp/Revolt can approximate it. Vs CSP (Go channels): actors own their mailbox; CSP channels are first-class.
Common Misconception
Why It Matters
Common Mistakes
- Sharing state between actors — defeats the model.
- Tight coupling via synchronous request-response chains — creates hidden deadlocks.
- Not implementing supervision trees — actors need a restart strategy.
Avoid When
- Simple single-threaded workloads — actor overhead adds complexity with no concurrency benefit.
- Synchronous request-reply patterns where actors must coordinate tightly — message passing adds latency.
- Teams unfamiliar with the paradigm — actor bugs (deadlocks via circular message waits) are subtle.
- Low-level performance code where actor message dispatch overhead is measurable.
When To Use
- Highly concurrent systems where shared mutable state causes contention — actors eliminate locks.
- Distributed systems where actors can be transparently placed on different nodes.
- Fault-tolerant systems — supervisor hierarchies let actors restart failed children automatically.
- Event-driven simulations, game engines, or real-time systems with many independent entities.
Code Examples
// Shared state between actors — violates the model:
class OrderActor {
public static array $orders = []; // Shared — race condition
}
// Elixir-style actor (conceptual PHP with Amp):
// Each actor has private state, communicates via channel:
$channel = new Amp\Channel\Channel();
$actor = Amp\async(function() use ($channel) {
$state = [];
while ($msg = $channel->receive()) {
// Process msg, update private $state
// Send reply back via $msg['replyTo']
}
});