Python Kafka multiprocess vs thread
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
For Python Kafka consumers, the choice between threads and processes depends on what happens after polling. If the consumer mostly waits on network I O, threads can be fine. If message handling is CPU-heavy, processes are usually the better way to scale.
Start with the Kafka Constraint
The first thing to remember is that a Kafka consumer instance is not a generic shared object you should pass around casually between worker threads. The safe pattern is usually:
- one consumer instance per thread or process
- or one dedicated consumer thread that hands work to workers
The more important design question is not "threads or processes" in isolation. It is "where does polling happen, and where does message processing happen."
When Threads Make Sense
Threads are a good fit when:
- the consumer spends most of its time waiting on Kafka and network I O
- downstream work is I O-bound
- you want lower overhead and shared memory
Example with a dedicated consumer thread and a worker queue:
This keeps Kafka polling centralized while still allowing concurrent downstream work.
When Processes Make Sense
Processes are the better choice when message handling is CPU-bound because they bypass the GIL and use multiple CPU cores more effectively.
Example:
Here each process creates its own consumer and joins the same consumer group. Kafka will divide partitions across them.
The Partition Limit Still Applies
Neither threads nor processes let you escape Kafka's partition model. Maximum parallel consumption for one consumer group is limited by the number of partitions in the topic.
If a topic has four partitions, then:
- one group can have at most four actively assigned consumers
- extra threads or processes in that group will sit idle
So scaling strategy should consider partition count first, not only Python concurrency primitives.
A Practical Rule of Thumb
Use threads when:
- the consumer mainly waits on I O
- message handlers call databases, APIs, or disks
- you want simpler shared-state coordination
Use processes when:
- handlers do CPU-heavy parsing, compression, ML inference, or crypto
- you want real parallel execution across cores
For many systems, the best design is hybrid:
- one consumer per process
- lightweight thread pool inside each process for I O-bound downstream calls
Offset Commit Considerations
Concurrency affects commit strategy too. If you poll in one place and process elsewhere, do not commit offsets too early. A message is only safely done after its processing actually completes.
That means your design should make it clear:
- who owns the consumer
- who decides when a record is finished
- when offsets are committed
Threads or processes do not solve that automatically.
Common Pitfalls
Sharing one consumer instance freely across many worker threads is a common source of unstable behavior and hard-to-debug bugs.
Using threads for CPU-heavy message processing often disappoints because the GIL prevents real parallel Python execution.
Spawning more consumers than there are topic partitions does not increase throughput for one consumer group.
Committing offsets before asynchronous processing finishes can cause data loss or skipped work after failures.
Summary
- Threads are usually better for I O-bound Kafka processing paths.
- Processes are usually better for CPU-bound message handling in Python.
- Keep consumer ownership explicit, typically one consumer per thread or per process.
- Partition count caps parallelism for a single consumer group.
- Choose concurrency model together with offset-commit strategy, not as an isolated implementation detail.
Related reading
- Python librdkafka producer perform against the native Apache Kafka Producer
- Python Mocking out Kafka for integration tests
- Python produce to different Kafka partition
- Python tutorial code from RabbitMQ failing to run
- Python requests - threads/processes vs. IO
- Python retrieve several URLs via select.epoll
- Python Keras An layer output exactly the same thing as input
- Python Keras LSTM learning converges too fast on high loss

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.