Зачем сравнивать RabbitMQ, Kafka и NATS JetStream
Эти системы решают одну бизнес-задачу — доставку сообщений между компонентами — но архитектурно устроены по-разному. Поэтому вопрос «кто быстрее» почти всегда неправильный: throughput, задержки, ordering и retention завязаны на модель хранения, подтверждения, конкуренцию потребителей и сценарий использования.
В продакшене выбор обычно упирается в пять вещей: нужен ли журнал событий на дни/недели, насколько важен порядок, сколько независимых потребителей, какие требования к задержке, и кто это будет администрировать. Ниже — практичная «ментальная модель» и эксплуатационные последствия.
Ментальная модель: очередь задач, commit log и pub/sub
RabbitMQ: брокер очередей и маршрутизация
RabbitMQ — классический message broker (AMQP) с богатой маршрутизацией: exchange → bindings → queue. Типовой паттерн — work queue: сообщение попадает в очередь, консьюмер забирает, подтверждает (ack), после чего сообщение исчезает. Встроены TTL, DLQ, ретраи, приоритеты, разные типы exchange (direct/topic/fanout/headers).
Философия: доставить «здесь и сейчас» и удобно разрулить маршруты. Персистентность возможна, но это не система для хранения «истории событий за вчера».
Kafka: распределённый commit log и стриминг
Kafka — распределённый журнал (commit log): топик разбит на партиции, внутри партиции сообщения строго упорядочены и имеют смещения (offset). Консьюмеры читают «вперёд» и сами управляют тем, что считается обработанным (commit offset). Retention — базовый механизм: хранить N часов/дней или до N гигабайт.
Философия: хранить историю событий и позволять независимым читателям воспроизводить её в своём темпе. Это делает Kafka сильной для event streaming, аналитики, CDC и реплея.
NATS JetStream: лёгкий pub/sub + персистентные стримы
NATS в основе — очень быстрый pub/sub с простой моделью subjects. JetStream добавляет персистентность: stream хранит сообщения, а consumers (push/pull) читают и подтверждают. По ощущениям это «стримы и очереди в одном стеке», обычно с меньшей операционной тяжестью, чем у Kafka, и более «стримовым» взглядом, чем у RabbitMQ.
Философия: быстрый messaging с возможностью retention и гарантированной доставки, при этом меньше компонентов и проще протокол — часто удачный вариант для микросервисов и control plane.

Ordering: где порядок гарантируется и какой ценой
Важный момент: глобальный порядок почти нигде не встречается. На практике порядок гарантируется в пределах сущности: очереди, партиции, конкретного consumer/subject. Чем сильнее гарантия, тем чаще вы платите параллелизмом и, как следствие, throughput.
RabbitMQ и порядок
В RabbitMQ порядок в очереди обычно сохраняется, но «ломается» на уровне обработки, если несколько консьюмеров, prefetch больше 1, задачи разной длительности и возможны повторные доставки. Получаются две реальности: порядок поступления в очередь и порядок завершения обработки.
Если нужен строгий порядок обработки, обычно делают один консьюмер на ключ или шардирование на несколько очередей по ключу (например, user_id), плюс контролируют prefetch и модель ack.
Kafka и порядок
Kafka гарантирует ordering внутри одной партиции. Если события одного ключа всегда попадают в одну партицию (через key), вы получаете строгий порядок по этому ключу и масштабируетесь количеством партиций.
Цена: один «горячий ключ» или топик с одной партицией быстро превращается в потолок по throughput и в один поток чтения. А очень много партиций усложняет балансировку и эксплуатацию.
NATS JetStream и порядок
JetStream хранит последовательность сообщений в stream, consumer получает их по порядку. Но как только вы распараллеливаете обработку (несколько consumers или пул pull-воркеров), возвращается классическая проблема: порядок доставки не равен порядку завершения.
Практически, «идеальный ordering» достигается проектированием: выбрать ключ шардирования, ограничить параллелизм для одного ключа и зафиксировать идемпотентность.
Почти всегда выгоднее проектировать обработку идемпотентной и допускающей повтор/перестановку, чем любой ценой удерживать строгий глобальный ordering.
Retention: сколько хранится история и как это влияет на архитектуру
RabbitMQ: retention как исключение
RabbitMQ умеет хранить сообщения на диске (durable queues, persistent messages), но это не retention в смысле «истории». Сообщение обычно живёт до ack или до истечения TTL. Да, можно строить DLQ/TTL/отложенную доставку, но «перечитать события за вчера» — не его сильная сторона.
Отдельный нюанс: большие очереди с долгоживущими сообщениями могут заметно влиять на производительность и время восстановления после перезапуска. Решается дисциплиной в TTL, DLQ, лимитах и контролем роста очередей.
Kafka: retention — фундаментальная фича
Kafka проектировалась вокруг retention. Вы храните события часами/днями, читатели приходят и уходят, делают replay и догоняют отставание. Это удобно для интеграций, аудита и CDC. Управление диском и жизненным циклом сегментов — часть нормальной эксплуатации.
Важно: retention не бесконечен. Заранее прикиньте объём событий, срок хранения и репликацию, иначе диск закончится «в самый интересный момент». Для бэкапов и политики хранения вне брокера полезно держать отдельный процесс: жизненный цикл хранения бэкапов и retention в S3-совместимых хранилищах.
NATS JetStream: retention «по делу»
JetStream поддерживает политики retention (в духе «хранить N времени», «лимит по размеру», «пока интересно хотя бы одному consumer»). Это удобно, когда нужна история «на часы/дни» для восстановления, ретраев и дедупликации, но не нужен «полный комбайн» экосистемы Kafka.
Практический плюс: можно добавить персистентность в систему, которая раньше была чистым pub/sub, и повысить надёжность без полной смены архитектуры.
Throughput и задержки: что реально ограничивает скорость
Ограничители почти всегда одинаковые: диски при персистентности, сеть при большом fanout, размер сообщений, количество подтверждений и модель потребления (push/pull, batch, prefetch).
RabbitMQ: скорость через параллелизм и правильные ack
RabbitMQ хорош для «много мелких задач» и «сложная маршрутизация». Но throughput резко меняется от режима подтверждений, prefetch, размера сообщения и того, пишете ли вы на диск. Плохой баланс между параллелизмом и ack часто даёт либо низкую скорость, либо лавинообразные повторы при сбоях.
Практика: держите сообщения небольшими, избегайте «гигантских payload». Большие данные лучше хранить в БД/объектном хранилище, а в брокер передавать ссылку и метаданные.
Kafka: throughput через партиции и батчи
Kafka добивается высокой пропускной способности за счёт последовательной записи в лог, батчинга и параллелизма по партициям. Если нужно «очень много событий в секунду» и «хранить историю» — это один из лучших кандидатов.
Цена — дисциплина: число партиций, ключи, настройки продюсера (батчи, компрессия), и мониторинг lag. Иначе вы получите ситуацию «всё зелёное, но консьюмеры никогда не догоняют».
NATS JetStream: низкие задержки и разумная персистентность
NATS известен низкими задержками в pub/sub. JetStream добавляет хранение, и throughput начинает зависеть от настроек stream/consumer, выбранного storage (memory/file), лимитов и модели подтверждения/повторов.
Если важны latency и простота протокола, но нужен retention и ack, JetStream часто оказывается хорошим компромиссом «достаточно быстро и достаточно надёжно».

Гарантии доставки: at-most-once, at-least-once, exactly-once
В продакшене «exactly-once» чаще превращается в «at-least-once доставка + идемпотентная обработка». Во всех трёх системах повторы возможны, различаются только механизмы и типичные места, где они проявляются.
RabbitMQ: типично at-least-once с
ack. Повторы возникают при падениях консьюмера/канала/сети. Закладывайте идемпотентность, используйте DLQ и лимитируйте ретраи.Kafka: at-least-once по умолчанию; повторы возможны при ребалансировках и ретраях. Есть инструменты для «почти exactly-once» (транзакции/идемпотентный продюсер), но это усложняет эксплуатацию и не всегда оправдано.
NATS JetStream: at-least-once с
ack. Есть дедупликация публикаций по msg-id и контроль повторной доставки, но идемпотентность обработчика всё равно критична.
Операционная сложность: что проще поддерживать
RabbitMQ
Обычно легко стартовать: один брокер, понятные очереди, просто объяснить разработчикам. Сложность растёт, когда появляется много очередей, ретраи, приоритеты, тонкая маршрутизация и требования к HA: quorum очереди, контроль памяти/диска, диагностика «почему выросла очередь и всё замедлилось».
Если поднимаете RabbitMQ на отдельной виртуалке и включаете шифрование/метрики, пригодится практический разбор: TLS и мониторинг RabbitMQ на VDS. Для продакшена часто удобнее держать брокер на VDS, чтобы контролировать диск и сеть.
Kafka
Kafka требует «операционного взросления» сразу: диски, сеть, наблюдаемость, грамотные настройки, планирование партиций и retention. В больших потоках и при длинном retention она обычно окупается, но на маленьких задачах может оказаться оверкиллом.
NATS JetStream
JetStream часто легче по когнитивной нагрузке и инфраструктурному следу, особенно если сравнивать «как быстро поднять» и «как быстро дебажить». Но важно помнить: JetStream — это не просто NATS. Хранение, лимиты, retention и понимание consumers/ack обязательны, иначе можно получить неожиданные повторы или рост диска.
Практические сценарии выбора
1) Очередь задач: воркеры, email, обработка файлов
Часто выбирают RabbitMQ: богатая маршрутизация, удобные DLQ/TTL, привычная модель «взял задачу → сделал → ack».
JetStream тоже подходит, если вы хотите унифицировать pub/sub и очереди в одном стеке и держать низкие задержки.
Kafka для чистой work queue тоже применяют, но чаще это оправдано, если события одновременно нужны как журнал (а не только «задачи на обработку»).
2) Event streaming: трекинг, аудит, CDC, реплей
Часто выбирают Kafka из-за retention и модели партиций/offset. Это прямое попадание в задачу «хочу журнал событий, который можно переигрывать».
JetStream может закрыть часть таких кейсов, если объёмы умеренные и важнее простота, чем экосистема вокруг Kafka.
RabbitMQ в таких сценариях обычно начинает «скрипеть»: слишком много логики приходится строить поверх очередей.
3) Микросервисы и обмен событиями между сервисами
Если нужен лёгкий транспорт и много pub/sub паттернов — NATS (и JetStream там, где нужна надёжность и повторная доставка) часто выглядит органично.
RabbitMQ тоже подходит, особенно если уже есть AMQP-стек и нужна сложная маршрутизация. Kafka обычно берут, когда межсервисные события одновременно являются бизнес-логом и должны храниться.
Частые ошибки при сравнении и пилотировании
Сравнивать throughput без одинаковых условий. Персистентность, подтверждения, размер сообщения, компрессия, батчи и число потребителей меняют цифры радикально.
Считать ordering глобальным. Везде ordering локальный. Планируйте ключ шардирования и думайте о параллелизме.
Игнорировать ретраи и DLQ. Ретраи без предела превращают частичный сбой в вечную «мясорубку».
Класть большие payload в сообщения. Упрётесь в сеть/диск/GC. Чаще лучше «payload в хранилище, в брокер — ссылку».
Не закладывать наблюдаемость. Нужны метрики: lag (Kafka), размер очередей и скорость
ack(RabbitMQ), состояние consumers/stream/хранилища (JetStream), плюс алерты на диск и задержки.
Мини-чеклист: как выбрать быстро, но не ошибиться
Нужен ли retention как у журнала на дни/недели и replay для разных потребителей? Обычно Kafka.
Нужна ли «очередь задач» с DLQ/TTL/маршрутизацией и привычным
ack? Часто RabbitMQ.Нужны низкие задержки pub/sub, простая модель subjects, и при этом надёжность/персистентность в части потоков? Смотрите NATS JetStream.
Если важен ordering по ключу — заранее определите ключ и шардирование (партиции/очереди/consumers), иначе потом будет дорого.
Гоняйте пилот на своих данных: размер сообщений, peak-нагрузка, задержки обработки, поведение при падениях, скорость восстановления, рост диска при retention.
Итог
RabbitMQ сильнее как брокер очередей и маршрутизации для задач и интеграций; Kafka — как высокопроизводительный журнал событий с retention и масштабированием через партиции; NATS JetStream — как лёгкий и быстрый messaging с персистентными стримами. Выбирайте от требований к ordering, retention и throughput, а не от «кто моднее»: в своей зоне каждая из систем будет и быстрее, и надёжнее, и дешевле в сопровождении.


