newsmode
search
Меню
arrow_back Назад

The safety of speed: How we ship code 180 times per day

auto_awesomeКраткое саммари

Intercom рассказывает, как им удаётся выкатывать код в production около 180 раз за рабочий день со средним временем от мерджа до использования клиентами всего в 12 минут при целевой доступности 99,8%+. В январе 2026 года инженеры компании опираются на три слоя защиты: автоматизированный pipeline (сборка, параллельный CI, проверка в pre-production, rolling restart на тысячах виртуальных машин), shipping workflow с принципом «будь рядом, когда выкатываешь», активным использованием feature flags (создано более 560 флагов за три месяца) и GitHub Scientist, и модель восстановления, основанную на heartbeat-метриках и автоматических откатах. Главный фокус статьи — Ruby on Rails monolith, который деплоится в три региона хостинга. Инженеры лично следят за метриками после ship и могут тестировать предрелизный slug на отдельных production-машинах. Авторы подчёркивают: скорость — это не враг стабильности, а её предпосылка, потому что маленькие частые изменения снижают риск, а накапливаемый код его увеличивает.

“Speed is not the enemy of safety; it is the prerequisite for it.”

«Скорость — не враг безопасности; она её необходимое условие».

At Intercom, the average time from merging code to it being used by customers in production is just 12 minutes.

В Intercom среднее время от мерджа кода до его использования клиентами в production составляет всего 12 минут.

In January 2026, we are averaging 180 ships per workday – roughly 20 deployments every hour. Conventional wisdom suggests that to increase stability, you must slow down. We believe the opposite. At Intercom, speed is not the enemy of safety; it is the prerequisite for it. Accumulating code creates risk; shipping small batches minimizes it. Shipping is our company’s heartbeat

В январе 2026 года мы в среднем делаем 180 ship’ов за рабочий день — примерно 20 деплоев в час. Принято считать, что для повышения стабильности нужно замедляться. Мы убеждены в обратном. В Intercom скорость — не враг безопасности, а её предпосылка. Накопленный код порождает риск; выкатки маленькими порциями его минимизируют. Shipping — это пульс нашей компании.

Maintaining this frequency that fuels our product innovation, while targeting 99.8+% availability is a constant battle and has required over a decade of significant investment in systems, principles and processes. We protect the integrity of our systems through three distinct layers of defense: an automated pipeline that is simple, reliable and removes the need for manual intervention, a shipping workflow that promotes ownership and is flexible enough to provide guardrails that act as accelerants, and a recovery model optimising for mitigating inevitable failures. Here is how we’ve built each layer to ensure our velocity remains our greatest source of stability.

Поддерживать такую частоту, которая питает наши продуктовые инновации, и одновременно стремиться к доступности 99,8%+ — это постоянная борьба, потребовавшая более десяти лет существенных инвестиций в системы, принципы и процессы. Мы защищаем целостность наших систем тремя отдельными слоями обороны: автоматизированный pipeline, который прост, надёжен и не требует ручного вмешательства; shipping workflow, поощряющий ответственность и достаточно гибкий, чтобы guardrails работали ускорителями; и модель восстановления, оптимизированная для смягчения неизбежных сбоев. Вот как мы построили каждый слой, чтобы наша скорость оставалась главным источником стабильности.

While Intercom consists of various services and frontend applications, this post focuses on our Ruby on Rails monolith. It is our core application and the one we deploy most frequently; we also deploy it to three different data-hosting regions with independent pipelines. While our other services (such as our Intercom UI) follow similar pipeline principles and safeguards, the Rails monolith is the best example of how we ship code at our scale.

Хотя Intercom состоит из множества сервисов и фронтенд-приложений, эта статья посвящена нашему монолиту на Ruby on Rails. Это наше основное приложение, которое мы деплоим чаще всего; кроме того, мы выкатываем его в три разных региона хостинга данных с независимыми pipeline’ами. Хотя другие сервисы (например, наш Intercom UI) следуют схожим принципам и защитным механизмам, монолит на Rails — лучший пример того, как мы доставляем код в нашем масштабе.

The automated pipeline

Автоматизированный pipeline

Designed to move code from merge to production as fast as possible while enforcing strict safety checks, our pipeline is optimized for speed and safety and is entirely automated with the majority of releases requiring no human intervention.

Спроектированный, чтобы как можно быстрее довести код от мерджа до production, обеспечивая при этом строгие проверки безопасности, наш pipeline оптимизирован одновременно для скорости и безопасности и полностью автоматизирован — большинство релизов не требуют участия человека.

Build and parallel testing

Сборка и параллельное тестирование

The process begins when an engineer merges code to GitHub. Two things happen immediately:

Процесс начинается, когда инженер мерджит код в GitHub. Сразу же происходят две вещи:

  • The build: We compile the Rails application and its dependencies into a deployable asset that we call a slug. This takes four minutes.
  • Parallel CI: Our test suite runs in parallel with the build. Through extensive optimization, parallelization and test selection, the vast majority of CI builds finish in under five minutes.
  • Сборка: мы компилируем Rails-приложение и его зависимости в развёртываемый артефакт, который называем slug. Это занимает четыре минуты. Параллельный CI: наш набор тестов запускается параллельно со сборкой. Благодаря масштабной оптимизации, параллелизации и отбору тестов подавляющее большинство CI-сборок завершается менее чем за пять минут.

    Pre-production verification

    Pre-production верификация

    Once built, the slug is deployed to a pre-production environment. CI does not block the progression of the slug to pre-production. Deploying to pre-production takes around two minutes. This environment serves no customer traffic, but it is connected to our production datastores and mirrors our production infrastructure variants (e.g. web serving, asynchronous worker) and is configured in a way that requests will exercise the pre-release code/workers.

    После сборки slug разворачивается в pre-production окружении. CI не блокирует переход slug’а в pre-production. Деплой в pre-production занимает около двух минут. Это окружение не обслуживает клиентский трафик, но подключено к нашим production-хранилищам данных и зеркалирует все варианты production-инфраструктуры (например, web-сервинг, асинхронные worker’ы), и сконфигурировано так, чтобы запросы проходили через предрелизный код/worker’ы.

    Immediately after deployment we run and await the result of several automated approval gates to verify the release. These answer questions including:

    Сразу после деплоя мы запускаем и ждём результаты нескольких автоматизированных approval gate’ов для верификации релиза. Они отвечают на вопросы вроде:

  • Boot test: Does the application initialise correctly on the host?
  • CI check: Did the parallel test suite pass?
  • Functional synthetics: We use Datadog Synthetics to run browser-based tests on critical flows, like loading or editing a Fin workflow.
  • Boot test: корректно ли приложение инициализируется на хосте? CI check: прошёл ли параллельный набор тестов? Functional synthetics: мы используем Datadog Synthetics для запуска браузерных тестов на критических флоу — например, загрузки или редактирования Fin workflow.

    If any gate fails, the release is halted and does not go to production. 

    Если какой-либо gate провалился, релиз останавливается и не попадает в production.

    Production rollout and rolling restarts

    Раскатка в production и rolling restarts

    Once the slug is approved for production, the code is promoted to thousands of large virtual machines. We use a deployment orchestrator to trigger these deployments simultaneously, but the actual rollout is decentralised.

    Как только slug одобрен для production, код продвигается на тысячи больших виртуальных машин. Мы используем оркестратор деплоя, чтобы запустить эти развёртывания одновременно, но фактический rollout децентрализован.

    This provides a staggered rollout, ensuring the entire fleet doesn’t change state at the exact same millisecond. Within these large virtual machines, we use a rolling restart mechanism at the process level:

    Это даёт ступенчатую раскатку, гарантируя, что весь флот не меняет состояние ровно в одну и ту же миллисекунду. Внутри этих больших виртуальных машин мы используем механизм rolling restart на уровне процессов:

  • An individual process with the old code is taken out of the customer-serving path
  • It is allowed to finish its current work and terminate gracefully once idle
  • It is replaced by a fresh process running the new code and returned to the serving path
  • Отдельный процесс со старым кодом выводится из пути обслуживания клиентов. Ему разрешают завершить текущую работу и корректно завершиться, как только он простаивает. Его заменяет свежий процесс с новым кодом, который возвращается в путь обслуживания.

    This process ensures that from the moment a deployment starts, the first requests are being served by new code within ~2 minutes. Within 6 minutes, the vast majority of our global fleet has been transparently updated without any downtime. When the restart is triggered on every machine, the pipeline unblocks production so the next deployment can begin.

    Этот процесс гарантирует, что с момента начала деплоя первые запросы обслуживаются новым кодом уже через ~2 минуты. В течение 6 минут подавляющее большинство нашего глобального флота прозрачно обновлено без какого-либо простоя. Когда restart запущен на каждой машине, pipeline разблокирует production, чтобы можно было начать следующий деплой.

    Monitoring pipeline health 

    Мониторинг здоровья pipeline’а

    If a piece of code doesn’t pass every safety check, it is automatically rejected before it ever touches a production server. Additionally we treat a stalled pipeline as a high-priority incident; if the automated system rejects three consecutive release attempts, it triggers a page to an on-call engineer.

    Если фрагмент кода не проходит каждую проверку безопасности, он автоматически отклоняется ещё до того, как коснётся production-сервера. Кроме того, остановившийся pipeline мы воспринимаем как инцидент высокого приоритета: если автоматизированная система отклоняет три релиза подряд, она отправляет page on-call инженеру.

    To a customer, waiting for three failures might sound like a lot, but these are pre-production blocks. We page a human at this stage because if the shipping lane stops moving, code changes begin to pile up. Our stability relies on building and shipping in small steps. If the pipeline stays blocked, those tiny steps merge into a large changeset which increases the risk of the next deployment. We page an engineer to fix the pipeline so we can return to the small, safe, and frequent updates that keep our systems stable.

    Для клиента ожидание трёх провалов может показаться долгим, но это блокировки pre-production. Мы поднимаем человека на этом этапе, потому что если линия доставки остановилась, изменения кода начинают накапливаться. Наша стабильность опирается на сборку и доставку маленькими шагами. Если pipeline остаётся заблокированным, эти крошечные шаги сливаются в большой changeset, что увеличивает риск следующего деплоя. Мы поднимаем инженера, чтобы починить pipeline и вернуться к маленьким, безопасным и частым обновлениям, которые поддерживают стабильность наших систем.

    The shipping workflow

    Shipping workflow

    While our pipeline is highly automated, the responsibility for the quality of our code lies with the engineer, not the tools. The decision to merge is a human one. Our workflow is built on the principle of extreme ownership; the engineer who writes the code is accountable for its success in production.

    Хотя наш pipeline сильно автоматизирован, ответственность за качество кода лежит на инженере, а не на инструментах. Решение о мердже — человеческое. Наш workflow построен на принципе крайнего владения: инженер, написавший код, отвечает за его успех в production.

    Be present when you ship

    Будь рядом, когда выкатываешь

    A core tenet of our culture is that you must be present when you ship. There is a practical benefit to our 12-minute deployment cycle: it keeps the engineer “in the zone.” When a deployment takes hours, engineers naturally move on to the next task, a meeting, or a lunch break. By the time their code hits production, their context is gone and they aren’t watching anymore.

    Один из ключевых принципов нашей культуры — ты должен быть рядом, когда выкатываешь. У нашего 12-минутного цикла деплоя есть практическая выгода: он удерживает инженера «в потоке». Когда деплой занимает часы, инженеры естественным образом переключаются на следующую задачу, встречу или обеденный перерыв. К моменту, когда их код доходит до production, контекст уже потерян, и они больше не следят.

    By keeping deployments fast, we ensure the engineer is still focused on the problem they just solved. To support this, our deployment system provides:

    Сохраняя деплои быстрыми, мы гарантируем, что инженер всё ещё сосредоточен на проблеме, которую только что решил. Чтобы это поддержать, наша система деплоя предоставляет:

  • Notifications: Automatically messages the engineer on Slack the moment their code is submitted and as it moves through the stages.
  • Observability links: Includes direct links to relevant dashboards and logs in every PR and Slack message.
  • Prompted verification: Encourages the engineer to actively “watch the dials” and test their feature as it goes live. It is not acceptable to rely on “green builds”. You’re expected to watch your change go live and if you’re not prepared to rollback, you’re not prepared to ship.
  • Уведомления: автоматически пишет инженеру в Slack в момент отправки его кода и по мере прохождения этапов. Ссылки на observability: включает прямые ссылки на нужные дашборды и логи в каждый PR и сообщение в Slack. Подсказка к проверке: побуждает инженера активно «следить за стрелками» и тестировать свою фичу, как только она поднимается. Полагаться на «зелёные сборки» неприемлемо. От тебя ожидают, что ты будешь смотреть, как твоё изменение уходит в production — и если ты не готов сделать rollback, ты не готов и ship’ить.

    We foster a no-blame culture focused on engagement. When we see an engineer trigger a rollback or open a revert immediately after a deployment, we don’t see it as a failure, we see it as a hallmark of an engineer who is actively watching their metrics and taking responsibility for the system’s health.

    Мы культивируем культуру без обвинений, ориентированную на вовлечённость. Когда мы видим, что инженер инициирует rollback или сразу после деплоя открывает revert, мы воспринимаем это не как провал, а как признак инженера, который активно следит за своими метриками и берёт ответственность за здоровье системы.

    Feature flags

    Feature flags

    We make extensive use of feature flags to turn deployment into a non-event. By decoupling deployment (moving code to servers) from release (turning features on), we remove the blast radius of a new feature. Flags can be enabled for all customers, a specific subset, or disabled for everyone in under 60 seconds through our backend UI. Engineers can flag small or large ones, group flags together into beta features, initiate phased rollouts etc. We’ve also invested in ensuring that these feature flags can be used in other non-Rails monolith applications. Flags can allow subsets of users to be opted in to behaviors for testing before wider release, protect against risky changes and everything in between. They’re heavily used at Intercom; we created over 560 flags in the past three months, and we actively manage them so they don’t turn into permanent complexity.

    Мы активно используем feature flags, чтобы превратить деплой в не-событие. Отделяя деплой (перенос кода на серверы) от релиза (включения фичи), мы убираем blast radius новой фичи. Флаги можно включить для всех клиентов, конкретного подмножества или выключить для всех менее чем за 60 секунд через наш бэкенд UI. Инженеры могут флагать маленькие или большие изменения, группировать флаги в beta-фичи, запускать поэтапные раскатки и т. д. Мы также инвестировали в то, чтобы эти feature flags можно было использовать в приложениях за пределами Rails-монолита. Флаги позволяют включать поведение для подмножеств пользователей для тестирования перед более широким релизом, защищают от рискованных изменений и многое между. Их активно используют в Intercom: за последние три месяца мы создали более 560 флагов и активно их сопровождаем, чтобы они не превращались в постоянную сложность.

    Experiment with GitHub Scientist

    Эксперименты с GitHub Scientist

    For complex refactors and especially ones where behaviour should not change, we leverage GitHub Scientist, an open source experimentation library. This allows us to run “candidate” logic (the new code) in parallel with “existing” logic (the old code) in production. Scientist auto-instruments both paths, comparing results and timing metrics in the background. Because only the existing behaviour is shown to the customer, we can iterate on and verify the new code under real production load without any risk to the user experience. When we’re confident that the candidate logic is correct, we can then seamlessly switch. 

    Для сложных рефакторингов — особенно тех, где поведение не должно меняться — мы используем GitHub Scientist, библиотеку для экспериментов с открытым исходным кодом. Она позволяет нам запускать «candidate»-логику (новый код) параллельно с «existing»-логикой (старым кодом) в production. Scientist автоматически инструментирует оба пути, сравнивая результаты и метрики времени в фоне. Поскольку клиенту показывается только существующее поведение, мы можем итеративно дорабатывать и проверять новый код под реальной production-нагрузкой без какого-либо риска для пользовательского опыта. Когда мы уверены, что candidate-логика верна, мы можем плавно переключиться.

    Manual verification 

    Ручная верификация

    Before merging code, engineers have the ability to generate a slug and deploy it to a virtual machine. Engineers can detach a running production machine from the customer-serving path and deploy their slug to it, connecting to the machine for manual testing. Engineers can also put their pre-release slug on a customer-serving machine where it will serve a small percentage of jobs or web requests in the fleet. Single hosts allow us to quickly filter our observability to these hosts and compare/contrast with the production release and generally makes low-level changes simpler and safer. 

    До мерджа кода у инженеров есть возможность сгенерировать slug и развернуть его на виртуальной машине. Инженеры могут отсоединить работающую production-машину от пути обслуживания клиентов и развернуть на ней свой slug, подключившись к машине для ручного тестирования. Инженеры также могут разместить свой предрелизный slug на машине, обслуживающей клиентов, где он будет обслуживать небольшой процент задач или web-запросов во флоте. Single hosts позволяют нам быстро фильтровать observability по этим хостам и сравнивать/сопоставлять с production-релизом, и в целом делают низкоуровневые изменения проще и безопаснее.

    We do this because staging is a simulation, but production is reality. No amount of pre-production testing can perfectly mimic the chaotic behavior of millions of users. By testing on a single production host, we validate our assumptions against real-world data without risking the entire fleet.

    Мы делаем это потому, что staging — это симуляция, а production — реальность. Никакое pre-production тестирование не может идеально имитировать хаотическое поведение миллионов пользователей. Тестируя на одном production-хосте, мы валидируем наши предположения на реальных данных, не рискуя всем флотом.

    Our recovery model

    Наша модель восстановления

    The size and complexity of Intercom and how our customers use the product in different and novel ways cannot be replicated by traditional non-production environments and testing. These things are still very important and have their place in our pipeline but failure in production is inevitable. Some of these failures will result in product degradation for customers and fewer still will result in an outage. 

    Размер и сложность Intercom, а также то, как клиенты используют продукт по-разному и нестандартно, нельзя воспроизвести традиционными непроизводственными окружениями и тестированием. Эти вещи по-прежнему очень важны и занимают своё место в нашем pipeline, но сбой в production неизбежен. Часть таких сбоев приведёт к деградации продукта для клиентов, а ещё меньшая часть — к outage.

    At Intercom, our approach to recovery is defined by one core principle: Stop monitoring systems; start monitoring outcomes. Traditional monitoring tells you if a server is healthy; our recovery model tells us if our customers are healthy.

    В Intercom наш подход к восстановлению определяется одним основным принципом: хватит мониторить системы; начните мониторить outcomes. Традиционный мониторинг говорит, здоров ли сервер; наша модель восстановления говорит нам, здоровы ли наши клиенты.

    Heartbeat metrics: the pulse of Intercom

    Heartbeat-метрики: пульс Intercom

    We rely on heartbeat metrics, which are vital signs that represent the core value our product provides. For Intercom, this includes the rate of comments created (new messages and replies).

    Мы опираемся на heartbeat-метрики — жизненно важные показатели, отражающие основную ценность, которую даёт наш продукт. Для Intercom это, в том числе, скорость создания комментариев (новых сообщений и ответов).

    Unlike standard uptime checks, these metrics are binary in spirit. If the rate of messages being sent drops below an expected baseline, it doesn’t matter if our dashboards are green. To a customer, down is down. If they can’t do their job, our uptime percentage is irrelevant. By tracking real-world success rates as a high level signal, we detect subtle degradations that traditional alerting either misses or over-alerts on.

    В отличие от стандартных проверок uptime, эти метрики по духу бинарны. Если скорость отправки сообщений падает ниже ожидаемого baseline, неважно, зелёные ли наши дашборды. Для клиента «лежит» значит «лежит». Если он не может делать свою работу, наш процент uptime неактуален. Отслеживая реальные показатели успешности как высокоуровневый сигнал, мы детектируем тонкие деградации, которые традиционные алерты либо пропускают, либо чрезмерно подсвечивают.

    Rapid recovery: rollbacks

    Быстрое восстановление: откаты

    Because we ship in small, incremental steps and maintain previous releases on the virtual machines, our Time to Recover (TTR) is generally very fast. 

    Поскольку мы ship’им маленькими инкрементальными шагами и держим предыдущие релизы на виртуальных машинах, наше Time to Recover (TTR) обычно очень короткое.

  • Automatic rollbacks: If a heartbeat metric drops or a critical anomaly is detected immediately following a ship, the system triggers an automatic rollback. The pipeline reverts the deployment to the release that was running 20 minutes ago. This often initiates service recovery before an engineer responds to the page. 
  • Manual rollbacks: For complex issues, engineers can trigger a rollback through our deployment UI.
  • Автоматические откаты: если heartbeat-метрика проседает или критическая аномалия детектируется сразу после ship’а, система запускает автоматический rollback. Pipeline возвращает деплой к релизу, который работал 20 минут назад. Это часто инициирует восстановление сервиса ещё до того, как инженер откликнется на page. Ручные откаты: для сложных проблем инженеры могут запустить rollback через наш deployment UI.

    Initiating a manual rollback also locks the production pipeline. This prevents further releases from going to production, giving us the space to remove the problematic code and investigate without impacting customers.

    Запуск ручного rollback также блокирует production pipeline. Это не даёт следующим релизам уйти в production, давая нам пространство, чтобы удалить проблемный код и провести расследование, не затрагивая клиентов.

    Hardening production

    Закаливание production

    Resumption of service is never the end of the process. Every incident leads to an incident review, but we don’t just fix the bug. We view every incident as a signal that our system allowed a failure. We ask: How did the machine allow this to happen? and we re-engineer the system to ensure it cannot happen again. By maintaining this loop of fast shipping, fast recovery, and rigorous learning, we ensure that our high velocity remains our greatest source of stability.

    Возобновление сервиса — никогда не конец процесса. За каждым инцидентом следует incident review, но мы не просто чиним баг. Мы рассматриваем каждый инцидент как сигнал того, что наша система допустила сбой. Мы спрашиваем: как машина позволила этому случиться? — и переинжиниринг системы так, чтобы это больше не могло повториться. Поддерживая этот цикл быстрой доставки, быстрого восстановления и тщательного обучения, мы гарантируем, что наша высокая скорость остаётся главным источником стабильности.

    Conclusion

    Заключение

    Shipping 180 times a day isn’t a vanity metric. It is a deliberate choice to protect the customer experience. When the window between writing code and customers using it is 12 minutes, the feedback loop is tight, and engineers retain the context and remain accountable for the immediate impact of their work.

    180 ship’ов в день — не метрика тщеславия. Это сознательный выбор ради защиты клиентского опыта. Когда окно между написанием кода и его использованием клиентами составляет 12 минут, петля обратной связи плотная, инженеры сохраняют контекст и остаются ответственными за непосредственное влияние своей работы.

    However, our bar is high. Maintaining this pace requires more than just fast CI; it requires engineers who exercise judgment and nail the basics of shipping safely. We rely on human expertise, augmented by these layers of defense, to catch issues before they turn into customer pain.

    Однако наша планка высока. Поддерживать такой темп требует большего, чем просто быстрый CI: нужны инженеры, которые проявляют здравый смысл и хорошо владеют основами безопасной доставки. Мы полагаемся на человеческую экспертизу, дополненную этими слоями обороны, чтобы ловить проблемы до того, как они превратятся в боль для клиента.

    At Intercom, we don’t ship fast despite our need for stability; we ship fast to stay in control of change.

    В Intercom мы ship’им быстро не вопреки потребности в стабильности; мы ship’им быстро, чтобы оставаться хозяевами изменений.