| Ordering unit | The message key — declared per message, no sizing | The partition — count chosen up front, hard to change | Message group ID | The queue (single consumer for strict order) |
| Parallelism | = number of active keys; nothing to configure | ≤ partition count | = active groups, but queue-level throughput caps apply | Consumers per queue; ordering lost beyond one |
| Head-of-line blocking | Failing message parks only its own key's lane | One bad message can stall its whole partition | Blocks its group until deleted or expired | Redelivery goes to the back or blocks, per config |
| Retries & backoff | Declared per subscription: attempts, backoff, jitter | Build it yourself (retry topics pattern) | Redrive policy to another queue; no backoff shaping | TTL + dead-letter-exchange plumbing, hand-built |
| Dead letter queue | Built in, browsable, grouped by error, one-call redrive | A convention (a topic you manage), not a feature | A second queue; browse/redrive via console | Dead-letter exchange; browsing is manual |
| Scheduled delivery | deliver_at any future time; durable, cancellable | Not built in | Delay up to 15 minutes only | Plugin or TTL tricks |
| Replay after ack | Seek by offset or time — even for a single key | Seek by offset/time (per partition, all keys) | Impossible — consumed messages are gone | Impossible — acked messages are gone |
| Per-message trace | Every attempt, consumer, error, duration, blocked_by | None (offsets only) | CloudWatch metrics, not per-message | None built in |
| Delivery guarantee | At-least-once, publish dedup window (honest about it) | At-least-once; EOS within Kafka-to-Kafka only | At-least-once (FIFO dedups publishes 5 min) | At-least-once |
| Runs on | Node.js + your MongoDB; one docker compose up | JVM cluster (+ ZooKeeper/KRaft); heavy ops | AWS-managed; AWS only | Erlang cluster; moderate ops |