One owner for live trading state. A queue for everything else.
On a real-time trading system I worked on, the dashboard, the market stream, and the simulation jobs all wanted to touch the same positions. That is how positions drift.
What we ran, as separate containers:
• Redis — the queue, the replies, and shared config. Not the position database.
• Celery Beat — the cron. It enqueues monitoring (30s), market data and analysis (5 min), risk (hourly), and a daily report. It never changes a position.
• Celery workers — simulations and those scheduled jobs, on their own queue.
• One manager worker — the only process allowed to change a live engine. Dashboard actions (start, stop, config) go to its queue, so a long simulation cannot block a stop.
The dashboard writes desired state to Postgres, then asks the manager through Redis. Heavy work stays off the live path. Same idea large chat systems use when they refuse to let every service rewrite a live session: one owner, a bus for the rest.
Coordination write-up, no strategy code: https://github.com/HarisUmer/trading-engine-redis-architecture
I build this kind of Python backend: Redis, Celery, and a single writer for the state that must not tear.