Unit 14.01: Workers, and what shared memory does not survive
Multiple workers means multiple copies of anything held in memory.
Five kinds of state, one of them fine
What four workers does to each kind of in-process state.
The code lists them.
STATE = [
("an in-memory rate-limit counter", "4 workers = 4x the limit"),
("an in-memory cache", "4 copies, 4 miss rates, no invalidation"),
("a module-level list of jobs", "a request may hit a worker that never saw it"),
("a background task in flight", "lost on restart, with no record"),
("a database connection pool", "correct -- per process, by design"),
]
print(f"{'in-process state':36} what 4 workers does to it")
for state, effect in STATE:
print(f"{state:36} {effect}")
print("""
Anything that must be shared has to live outside the process: Redis, the
database, or the gateway. Anything per-process is fine and should be created
once per worker, which is what the cached dependency in Module 7 does.
Testing with one worker hides every one of these.
""")
The rate-limit counter is the visible one - four workers means four times the limit - but the cache is worse, because four copies with independent invalidation produce inconsistent answers to identical requests.
The connection pool is the one that is correct as-is. It is per-process by design, and each worker having its own is the intended behaviour.
The mistake this prevents
The mistake is testing with one worker. Every one of these bugs is invisible then, and the symptoms in production - a limit that seems wrong, a cache that seems stale - look like logic errors rather than deployment ones.
Takeaway
Anything that must be shared belongs outside the process. Test with the worker count you deploy with, or these bugs stay hidden.
