Skip to content

Commit 4eaf3c8

Browse files
clarify throughput
1 parent 4345204 commit 4eaf3c8

1 file changed

Lines changed: 10 additions & 7 deletions

File tree

README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,8 +1537,8 @@ await messageQueue.publish("user.created", user); // 💥 Fails! User exists but
15371537

15381538
**Trade-offs:**
15391539

1540-
- Message queues: Lower latency (~10ms), higher throughput (10k+/s)
1541-
- txob: Tens of ms with wakeup signals (or `pollingIntervalMs`-bounded without), moderate throughput (10-100/s per processor)
1540+
- Message queues: Lower latency (~10ms), higher per-broker throughput (10k+/s) with dedicated buffering and fan-out primitives
1541+
- txob: Tens of ms with wakeup signals (or `pollingIntervalMs`-bounded without). Per-processor throughput is 10-100/s typical, but scales near-linearly with processor count until the database write ceiling — production deployments can reach 1k-10k+/s on a single Postgres/MongoDB. Ultimate ceiling is handler efficiency and DB write capacity, same as any consumer.
15421542

15431543
**Can I use txob WITH message queues?**
15441544

@@ -1809,9 +1809,11 @@ const processor = new EventProcessor<EventType>({
18091809

18101810
**Throughput:**
18111811

1812-
- Depends on handler speed and concurrency settings
1813-
- Single processor: 10-100 events/second typical
1814-
- Horizontally scalable: add more processors for higher throughput
1812+
- Single processor: 10-100 events/second typical, primarily bounded by handler speed and `maxEventConcurrency`
1813+
- Aggregate: scales near-linearly with processor count via `FOR UPDATE SKIP LOCKED` (Postgres) / per-document locking (MongoDB), no coordination required
1814+
- Production deployments can reach **1k-10k+ events/second** on a single well-tuned Postgres/MongoDB
1815+
- Ultimate ceilings are the same as any message-queue consumer: handler efficiency, downstream-system capacity, and database write throughput
1816+
- Where message queues genuinely win: fan-out / pub-sub to many independent consumers, cross-region replication, and dedicated burst buffering — not raw single-stream throughput
18151817

18161818
**Optimization:**
18171819

@@ -1886,7 +1888,8 @@ Add a `priority` column to your events table.
18861888

18871889
- You need **exactly-once semantics** (use Kafka with transactions)
18881890
- You need **hard real-time processing** (sub-10ms tail latency) - use message queue
1889-
- You need **high throughput** (> 10k events/second) - use message queue
1891+
- You need **fan-out / pub-sub** to many independent consumers - use message broker (txob handlers all run in the same processor process)
1892+
- You need **sustained throughput beyond your database's write capacity** - use a dedicated message system
18901893
- You already have **message queue infrastructure** you're happy with
18911894
- You can't make handlers **idempotent**
18921895
- You need **complex routing** or pub/sub patterns - use message broker
@@ -1898,7 +1901,7 @@ Add a `priority` column to your events table.
18981901
| Infrastructure | Database only | Separate service | Separate cluster | Managed service |
18991902
| Consistency | Strong (ACID) | Eventual | Eventual | Eventual |
19001903
| Latency | ~10s of ms with wakeup signals, ~5s polling-only | ~10ms | ~10ms | ~1s |
1901-
| Throughput | 10-100/s per processor | 10k+/s | 100k+/s | 3k/s |
1904+
| Throughput | 10-100/s per processor; 1k-10k+/s aggregate (DB-bound) | 10k+/s | 100k+/s | 3k/s |
19021905
| Horizontal scaling | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
19031906
| Exactly-once | ❌ No | ❌ No | ✅ Yes | ❌ No |
19041907
| Operational complexity | Low | Medium | High | Low |

0 commit comments

Comments
 (0)