Сравнение Zstd, Brotli и Gzip для сжатия ответов API: скорость, степень сжатия, задержка, поддержка клиентами и практические рекомендации внедрения.

Сжатие ответов API — это простой способ уменьшить объём данных, которые сервер отправляет клиенту. Для пользователя это часто означает более быстрые ответы и меньший расход трафика, а для бизнеса — экономию на передаче данных (egress) и более предсказуемую нагрузку на сеть.
Чаще всего сжимают текстовые форматы, которые хорошо «складываются» за счёт повторяющихся полей и структур:
А вот уже сжатые или плохо сжимаемые данные (JPEG/PNG, MP4, PDF, protobuf в некоторых схемах) обычно дают меньший эффект — иногда их вообще выгоднее не трогать.
Меньше трафика: особенно заметно на крупных JSON‑ответах и при высокой частоте запросов.
Меньше время передачи: чем меньше байтов надо «протолкнуть» по сети, тем ниже время загрузки, особенно на мобильных сетях и при высокой RTT.
Меньше стоимость egress: актуально для облаков и публичных API, где оплата часто зависит от объёма исходящего трафика.
Сжатие не бесплатное:
Accept-Encoding), и иметь корректный фолбэк.Один и тот же алгоритм может быть идеальным в одном случае и спорным в другом.
Сжатие ответа — это обмен «время CPU на сервере/клиенте» на «меньше байт по сети». Итоговую скорость определяет не только то, насколько хорошо алгоритм уменьшает размер, но и сколько времени уходит на (де)сжатие, плюс сетевые накладные расходы.
Большинство современных алгоритмов (и Gzip, и Brotli, и Zstd) опираются на два базовых шага:
Поиск повторов: алгоритм замечает, что куски данных повторяются (например, ключи JSON, одинаковые строки, повторяющиеся структуры) и заменяет повтор на короткую ссылку назад — условно «это уже было вот там».
Энтропийное кодирование: когда данные стали «более предсказуемыми» (много коротких ссылок, частые символы), их упаковывают так, чтобы частое занимало меньше бит, а редкое — больше.
Отдельная тема — словари: это заранее известный набор типичных фрагментов (например, характерные поля вашего JSON). Словарь помогает сжимать даже там, где внутри одного ответа повторов мало.
«Уровень» почти всегда означает степень усердия: насколько глубоко алгоритм ищет повторы и насколько тщательно подбирает представление.
Важно: скорость распаковки часто растёт не так сильно, как скорость упаковки. Поэтому для API типичный подход — сжимать умеренно, чтобы не ухудшать p95/p99 latency.
Текст (JSON, HTML, CSS) обычно хорошо сжимается: много повторяющихся ключей, пробелов, похожих фрагментов. Бинарные форматы (Protobuf, MessagePack) уже плотнее и содержат меньше очевидных повторов, поэтому выигрыш от сжатия может быть меньше.
При этом «уже бинарное» не значит «не сжимается»: если ответы большие и однотипные, сжатие всё равно может дать эффект.
У сжатия есть фиксированные накладные расходы: заголовки, служебные данные, время на запуск компрессора. Если ответ условно 200–500 байт, то:
Поэтому на практике часто вводят порог размера: сжимать только ответы больше N байт и только те Content-Type, где это действительно даёт смысл (например, JSON).
Brotli (br) — алгоритм сжатия, который чаще всего выигрывает на текстовых ответах: HTML, CSS, JS, JSON. Его любят за то, что при той же логике доставки он часто даёт меньший размер, чем gzip, а значит уменьшает трафик и ускоряет загрузку на медленных каналах. Для API это особенно заметно на «болтливых» JSON‑ответах с повторяющимися ключами.
С точки зрения совместимости Brotli сегодня — почти стандарт для веба:
br и отправляют его в Accept-Encoding.Практическое правило: для публичных веб‑клиентов Brotli можно смело включать, но для широкого спектра интеграций оставляйте фолбэк на gzip через стандартную HTTP‑схему Accept-Encoding.
Brotli чаще выбирают там, где много текстового контента и важен размер:
Accept-Encoding.Для внутренних микросервисов Brotli используют реже: там важнее суммарная CPU‑стоимость и предсказуемая задержка, а не минимальный размер любой ценой.
Главный плюс Brotli — эффективное сжатие текстовых форматов. На JSON это обычно выражается в меньшем размере, чем у gzip при сопоставимых настройках. Особенно хорошо работает на:
Если у вас API «упирается» в пропускную способность или стоимость трафика, Brotli часто даёт ощутимый эффект.
Компромисс Brotli — цена сжатия. На высоких уровнях он может:
Поэтому типичная практика: держать Brotli включённым для текстового контента, но выбирать умеренные уровни сжатия и опираться на кэширование (на CDN или на уровне приложения), чтобы не пересчитывать компрессию на каждый запрос.
Gzip — самый «понятный» и распространённый вариант компрессии для HTTP‑ответов. Во многих командах он остаётся выбором «по умолчанию» просто потому, что почти гарантированно будет поддержан клиентом и не принесёт сюрпризов в продакшене.
Исторически gzip поддерживается практически везде: браузеры, мобильные SDK, HTTP‑клиенты, CDN и старые корпоративные прокси. Если у вас публичный API и вы не контролируете клиентов, gzip часто становится самым безопасным базовым уровнем: клиент прислал Accept-Encoding: gzip — вы отдали сжатый ответ; не прислал — отдали обычный.
Главное преимущество gzip — предсказуемая совместимость по всей цепочке доставки. Даже если между сервером и потребителем стоят балансировщики, API‑шлюзы или промежуточные кэши, gzip обычно корректно проходит через них без дополнительных настроек. Это снижает риск редких багов вида «у части пользователей ответы внезапно перестали распаковываться».
На практике gzip удобно использовать как гарантированный «фолбэк» для случаев, когда более современные алгоритмы недоступны или отключены на стороне клиента.
Gzip легко включить в популярных веб‑серверах и прокси, легко мониторить и объяснять. Он даёт стабильный выигрыш на типичных текстовых payload’ах (JSON, HTML, CSS) и хорошо подходит для сценариев, где важнее минимизировать операционные риски, чем выжать максимум экономии трафика.
Компромисс — эффективность сжатия. На JSON и других текстовых ответах gzip нередко уступает Brotli и Zstd по итоговому размеру, а значит может проигрывать по задержке на медленных сетях или при дорогом трафике.
Поэтому gzip — отличный «универсальный минимум»: включить легко, работает почти везде, но если цель — максимальная экономия трафика и лучшая скорость загрузки у клиентов, обычно есть смысл рассматривать более современные варианты (с сохранением gzip как запасного пути).
Zstandard (Zstd) часто выбирают для API, когда важны и скорость, и экономия трафика. Его сильная сторона — очень быстрая распаковка при хорошем коэффициенте сжатия, из‑за чего задержка на клиенте обычно получается небольшой даже на слабых устройствах.
Для API Zstd интересен тем, что «дешевле» по CPU на распаковке, чем многие альтернативы, и при этом нередко сжимает заметно лучше, чем классический Gzip на сопоставимых настройках. Это помогает снизить время передачи (особенно на медленных сетях) без резкого роста нагрузки на клиентов.
Отдельный плюс — предсказуемость: на типичных API‑ответах (JSON, иногда protobuf‑байты, логи, большие списки) Zstd даёт стабильный баланс и редко оказывается «плохим выбором», если инфраструктура его поддерживает.
Микросервисы. Во внутренних вызовах много однотипных JSON‑ответов, и выигрыш часто выражается в меньшей сетевой нагрузке и меньшем общем времени ответа. Если сервисы общаются через прокси/mesh, имеет смысл проверить, пропускает ли он Content-Encoding: zstd и не ломает ли кеширование.
Мобильные клиенты. Экономия трафика и более быстрая распаковка на устройстве дают приятный эффект для UX. Здесь важно убедиться, что SDK/HTTP‑клиент умеет Zstd, иначе понадобится аккуратный фолбэк.
Большие JSON‑ответы. На длинных списках, каталогах, аналитике и «тяжёлых» payload’ах Zstd часто заметно сокращает размер, а распаковка остаётся быстрой.
На практике для API чаще всего выбирают низкие или средние уровни: они дают хороший прирост к размеру по сравнению с отсутствием сжатия, но не увеличивают время кодирования настолько, чтобы ухудшить latency.
Простое правило: если у вас много коротких ответов и критична задержка — берите более быстрый уровень. Если ответы крупные и повторяющиеся, и серверный CPU не узкое место — можно поднять уровень и посмотреть, окупается ли дополнительное сжатие по метрикам.
Главный стоп‑фактор Zstd — совместимость. Не все браузеры, CDN, прокси и корпоративные шлюзы одинаково хорошо принимают zstd в Accept-Encoding. Поэтому обычно делают так: сервер выбирает Zstd только если клиент явно его запросил, иначе отдаёт Gzip (или без сжатия), и обязательно тестируют цепочку целиком — от клиента до балансировщика и кеша.
Если вы не контролируете клиентов (публичный API), Zstd стоит включать как опцию с безопасным фолбэком, а не как единственный формат.
Сравнение Brotli, Gzip и Zstd «в вакууме» почти всегда приводит к неправильным выводам. Для API важно не только то, насколько уменьшается тело ответа, но и то, как это отражается на задержках и нагрузке на CPU при реальном профиле трафика.
Минимальный набор метрик, который имеет смысл собирать для API:
Отдельно фиксируйте, где именно меряете: «чистое» время кодека или полную серверную обработку (с сериализацией JSON, сетевым стеком и т. п.).
Кодеки по‑разному реагируют на структуру полезной нагрузки:
Поэтому сравнивайте не «JSON вообще», а ваши типовые ответы: например, /users, /search, /feed, /metrics.
Сделайте минимум три набора, чтобы не экстраполировать результаты:
Для каждого набора прогоняйте несколько уровней качества (например, по 2–3 уровня на кодек), иначе сравнение будет нечестным: «максимальный Brotli» против «дефолтного gzip» редко отражает реальную эксплуатацию.
Чтобы результаты были применимы:
Итог: хорошая методика сравнения — это не один бенчмарк, а набор измерений, где вы видите компромисс «байты ↔ CPU ↔ хвостовые задержки» именно на ваших API‑ответах.
Сжатие в HTTP — это не только выбор алгоритма, но и корректная «договорённость» между клиентом и сервером. Ошибки в заголовках часто приводят к странным багам: сломанному кешу, двойному сжатию или непредсказуемому поведению через прокси.
Клиент сообщает, какие кодеки он понимает, через Accept-Encoding. Сервер выбирает один вариант и отвечает с Content-Encoding.
Пример типичного запроса:
Accept-Encoding: br, gzip, zstd
Ответ сервера:
Content-Encoding: br
Если клиент указывает «веса» (q-values), сервер должен учитывать приоритеты:
Accept-Encoding: br;q=1.0, gzip;q=0.8, *;q=0.1
Важно: если сервер сжимает ответ, меняется представление ресурса. Поэтому почти всегда нужно добавлять:
Vary: Accept-Encoding
Иначе общий кеш (CDN, прокси, корпоративный кеш) может сохранить сжатую версию и отдать её клиенту, который сжатие не поддерживает.
Правило простое: сервер выбирает лучший из поддерживаемых клиентом вариантов, иначе отдаёт «как есть» (без Content-Encoding). На практике для публичных HTTP API чаще всего безопасный порядок такой:
br для браузерных клиентов (широкая поддержка)gzip как универсальный запасной вариантzstd — отлично подходит для контролируемых клиентов (мобильные приложения, SDK, сервис‑к‑сервису), но поддержка на «краю» (браузеры, некоторые прокси) может быть ограниченаЕсли вы решаете включать zstd, убедитесь, что клиенты реально отправляют Accept-Encoding: zstd, и что промежуточные устройства не вычищают этот токен.
Прокси, API‑шлюзы и CDN часто делают две вещи: модифицируют заголовки и кешируют ответы. Отсюда ключевые проверки:
Не допускайте двойного сжатия. Если апстрим уже отдал Content-Encoding: gzip, даунстрим не должен «сжать ещё раз». Обычно это решается настройкой, что сжатие выполняется в одном месте (например, на edge) и отключается на остальных слоях.
Кеш должен различать варианты. Vary: Accept-Encoding обязателен, иначе возможна выдача «не того» байтового представления.
ETag/Content-Length. При сжатии меняются и длина, и хеш. Если вы генерируете ETag на базе тела, он должен соответствовать конкретной кодировке. С Content-Length проще: при потоковой отдаче сервер может перейти на chunked и не считать длину заранее.
Сжатие не всегда полезно. Его обычно отключают для:
image/png, image/jpeg, image/webp, video/*, audio/*application/zip, application/gzip, application/x-7z-compressed, application/pdfДля JSON/текста сжатие почти всегда окупается, но только если заголовки и кеширование настроены аккуратно — тогда вы получаете экономию трафика без сюрпризов в совместимости.
Настройки сжатия для API лучше начинать с простых правил, которые дают заметный выигрыш без лишней нагрузки на CPU. Здесь нет «идеального уровня»: выбор — это баланс между экономией трафика и добавленной задержкой на сжатие.
Практическое правило: если ваши p95/p99 задержки чувствительны, начинайте с умеренных уровней (gzip 5, brotli 4–5, zstd 3) и повышайте только после измерений.
Сжатие имеет фиксированные накладные расходы (заголовки, работа CPU). Поэтому включайте его только для ответов больше N байт. Типичные стартовые значения:
Сжимайте в первую очередь:
application/json, application/problem+jsontext/* (например, text/plain, text/csv)Не сжимайте (обычно бесполезно или рискованно):
image/*, video/*, application/zip, application/pdfГлавное правило: не сжимайте ответы, где в одном теле смешиваются секреты и отражённые данные пользователя (класс атак типа BREACH/CRIME). Для API это часто означает осторожность с:
Для ошибок (4xx/5xx) полезно быть аккуратнее: либо включать сжатие только после порога размера, либо держать сообщения лаконичными — так вы снизите и риски, и шум в логах.
Если вы отдаёте сжатие, обязательно добавляйте Vary: Accept-Encoding. Иначе CDN/прокси может закешировать gzip‑версию и отдать её клиенту, который её не поддерживает.
Учтите, что Vary увеличивает количество вариантов объекта в кеше (по сути, разные ключи для gzip/br/zstd/identity), поэтому:
Выбор алгоритма сжатия для API почти всегда зависит не от «кто лучше в вакууме», а от сценария: какая сеть, сколько запросов в секунду, насколько дорог CPU и как ведут себя клиенты.
Для мобильных клиентов обычно критичны два параметра: объём передаваемых данных и «время до первого полезного байта». При плохой сети даже несколько лишних килобайт на каждом ответе превращаются в ощутимую задержку, поэтому более сильное сжатие часто выигрывает.
Практика такая: если у вас много JSON (профили, ленты, каталоги), то Brotli нередко даёт лучший размер, но может потребовать больше CPU на сервере и иногда на клиенте. Zstd часто оказывается удачным компромиссом: размер чуть хуже, зато компрессия/декомпрессия быстрее — это важно, когда приложение делает много запросов подряд.
Ещё один нюанс: батарея и нагрев. Если клиент — слабое устройство, слишком «тяжёлая» декомпрессия может нивелировать выигрыш от меньшего трафика. Поэтому стоит протестировать на реальных устройствах (не только в эмуляторе) и не ставить максимальные уровни «на всякий случай».
При большом RPS компрессия начинает конкурировать за CPU с бизнес‑логикой. Тут победит не тот алгоритм, который сжимает сильнее, а тот, который даёт минимальную суммарную задержку и не «съедает» ядра.
Типичный подход:
В таких условиях Zstd часто удобен как «быстро и достаточно эффективно». Gzip — безопасный вариант по совместимости, но при тех же бюджетах CPU иногда проигрывает по времени.
Если микросервисы общаются в одном датацентре, сеть обычно быстрая и дешёвая, а задержки чаще завязаны на очереди, базы и сериализацию. Сжатие может:
Здесь разумно включать компрессию точечно: для «толстых» ответов, межрегионального трафика или когда сервисы ходят через более дорогие каналы.
При частых коротких ответах (много мелких запросов) сжатие может почти не помочь: заголовки и накладные расходы компрессора становятся сравнимы с полезной нагрузкой. Лучше увеличить гранулярность (пакетировать данные), либо поднять порог, при котором включается сжатие.
Для стриминга важны размеры чанков: слишком маленькие чанки хуже «сжимаются» и увеличивают расходы на обработку. Если вы отдаёте данные порциями, тестируйте разные размеры порций и смотрите не только на итоговый размер, но и на задержку между порциями.
Если нужен «без сюрпризов» вариант для большинства клиентов и прокси, Gzip остаётся самым безопасным базовым выбором: его поддерживают почти везде, а поведение хорошо предсказуемо.
Если основная аудитория — браузеры и вы отдаёте много текстового контента (JSON, HTML, CSS, JS), часто выигрывает Brotli: он обычно даёт меньший размер на проводе при приемлемой цене по CPU.
Если вы контролируете клиентов (мобильное приложение, SDK, внутренние сервисы) и хотите баланс «скорость сжатия/размер/latency», рассмотрите Zstd — но только при уверенной поддержке на стороне клиентов и вашей инфраструктуры.
Если вы быстро собираете и развиваете API (например, админки, каталоги, личные кабинеты) и при этом хотите держать под контролем latency и стоимость трафика, компрессию проще закладывать как стандартную часть пайплайна.
В TakProsto.AI — вайб‑кодинг платформе для российского рынка, которая генерирует веб (React), бэкенд (Go + PostgreSQL) и мобильные приложения (Flutter) из чата — такие «инфраструктурные» вещи удобно фиксировать на уровне шаблонов/проектных настроек: пороги сжатия, список Content-Type, фолбэки по Accept-Encoding, а затем проверять эффект в метриках и откатываться через снапшоты/rollback, если хвосты p95/p99 ухудшились.
Измерить текущее состояние. Соберите базовую линию по размеру ответов, CPU на сервисе и p95/p99 latency.
Включить сжатие для части трафика. Начните с малого: отдельный маршрут, отдельный пул, канареечный релиз или 5–10% запросов.
Сравнить по p95, а не только по «среднему». Часто сжатие улучшает среднюю задержку, но может ухудшить хвосты из‑за CPU и конкуренции за ресурсы.
Расширить охват. Если хвосты не просели и выигрыш по трафику заметен, увеличивайте долю и добавляйте типы ответов.
Accept-Encoding, распределение по алгоритмам.Content-Encoding и Vary: Accept-Encoding.Accept-Encoding, отдавайте несжатый ответ или более совместимый алгоритм.Итог простой: начните с совместимого варианта, измеряйте хвосты задержек, и включайте более «сильные» алгоритмы только там, где они реально дают выигрыш на ваших данных и клиентах.
Сжатие уменьшает объём данных в ответе, что обычно даёт:
Но сжатие добавляет CPU и может ухудшить хвостовые задержки, если настроено агрессивно.
В первую очередь — текстовые форматы, которые хорошо «складываются» за счёт повторов:
application/json и родственные (application/problem+json);text/* (например, text/plain, text/csv);Обычно не стоит сжимать уже сжатые данные (image/*, video/*, application/zip, application/pdf) — выигрыш маленький, а CPU тратится.
Потому что у сжатия есть фиксированный оверхед: служебные байты кодека и время на запуск/работу компрессора. На ответах порядка сотен байт экономия может быть близка к нулю (или даже «в минус»), а задержка и CPU — реальными.
Практика: введите порог, например от 1 КБ для JSON/текста (и поднимайте до 2–4 КБ, если у вас много мелких ответов и критичен CPU).
Accept-Encoding — что умеет клиент (например: br, gzip, zstd).
Content-Encoding — чем сервер реально закодировал ответ.
Если вы отдаёте сжатые варианты, почти всегда добавляйте:
Vary: Accept-EncodingИначе кеш (CDN/прокси) может сохранить, например, gzip-версию и отдать её клиенту, который gzip не поддерживает.
Типичная безопасная схема для публичного API:
Accept-Encoding;Content-Encoding (identity).На практике часто держат:
Обычно Brotli выигрывает на текстовых ответах (HTML/CSS/JS/JSON) по итоговому размеру. Это полезно, когда важны байты на проводе: мобильные сети, дорогой трафик, большие JSON.
Но на высоких уровнях Brotli может заметно грузить CPU при сжатии «на лету», поэтому для динамического API чаще выбирают умеренные уровни и полагаются на кеширование.
Gzip выбирают из-за предсказуемой совместимости: его понимают почти все клиенты, прокси, балансировщики и корпоративные шлюзы.
Если у вас публичный API с неизвестными интеграциями, gzip часто становится базовым «без сюрпризов» вариантом. Минус — на текстовых данных он нередко проигрывает Brotli/Zstd по размеру.
Zstd часто даёт хороший баланс: прилично сжимает и обычно быстро распаковывается, что помогает удерживать latency.
Подходит для:
Главный стоп‑фактор — совместимость: включайте Zstd только для клиентов, которые явно его запросили (Accept-Encoding: zstd) и после проверки всей цепочки (прокси/CDN/mesh).
Стартовые «умеренные» настройки, которые часто дают хороший баланс:
Дальше корректируйте по метрикам (особенно p95/p99): иногда +1 уровень почти не уменьшает размер, но заметно увеличивает CPU.
Сравнивайте не «в вакууме», а на ваших типовых ответах и под ваш профиль нагрузки. Минимальный набор метрик:
Прогоняйте тесты на разных размерах (малые/средние/большие ответы) и фиксируйте сценарий (сжатие на лету vs из кеша).
br для браузерных клиентов;gzip как самый совместимый фолбэк;zstd как опцию для контролируемых клиентов (SDK/мобайл/сервис‑к‑сервису), если инфраструктура пропускает.