Инженерия
Как устроены системы, которые нельзя останавливать. Платёжные ядра, миграции живых баз, требования регуляторов, производительность под нагрузкой. Пишем о решениях, которые принимали сами, — вместе с ценой ошибки и тем, что сделали бы иначе.
Тесты не доказывают отсутствие бага. Что доказывает
Коротко: набор тестов — это поиск. Он умеет сказать «нашёл» и не умеет сказать «нет». Для большей части кода этого достаточно, но не для протокола оплаты, конечного автомата заказа и любого места, где две задачи трогают общее состояние: там редкое сочетание шагов и есть баг. Проверка моделей обходит все достижимые состояния и отвечает на вопрос, на который тесты не отвечают в принципе.
Уровни изоляции: что ваша база разрешает на самом деле
Коротко: уровень изоляции — это не настройка производительности, а список того, что вашему приложению разрешено увидеть. Между «read committed» и «serializable» лежат аномалии с именами и с ценой: списание сверх остатка, две смены без дежурного, задвоенный документ. Прочитать в документации, что база «поддерживает snapshot isolation», недостаточно — это свойство исполнений, а не текста.
Падает мастер: что на самом деле происходит с вашими данными
Коротко: «у нас кластер из трёх узлов» — это описание конфигурации, а не свойство системы. Свойство появляется тогда, когда кто-то проверил: при разделении сети два узла не решат одновременно, что они главные, а запись, подтверждённая клиенту, не исчезнет вместе с упавшим лидером. Проверяется это симуляцией, а не выключением сервера руками.
Тест падает раз в триста прогонов. Это не погода
Коротко: тест, который падает раз в триста прогонов, уже нашёл настоящую гонку — вы просто не можете её повторить. Случаен не баг, а порядок выполнения, который выбрала операционная система. Отберите у неё этот выбор — и падение из анекдота превращается в адрес.
Повтор запроса не должен списывать деньги дважды
Коротко: сеть не сообщает, прошёл платёж или нет, — она просто молчит. Клиент нажимает кнопку второй раз, мобильное приложение повторяет запрос само, и без защиты вы списываете дважды. Разбираем, как устроена идемпотентность на уровне таблиц и кода и где её обычно ломают.
LCP 6,4 секунды из-за заслонки, которую никто не видел
Коротко: разбор нашего собственного сайта. Текст первого экрана приезжал с сервера за 10 миллисекунд, а появлялся на экране через шесть с половиной секунд — его закрывала интро-заставка, снять которую мог только загрузившийся JavaScript. После починки LCP 6,4 → 2,2 с, оценка производительности 73 → 98. Ниже — как искали, включая гипотезу, которая оказалась неверной.
Как переносят базу под нагрузкой и не теряют записи
Коротко: перенос «в ночь на воскресенье» — это не план, а ставка. Рабочий приём другой: некоторое время система пишет в оба хранилища сразу, история переносится фоном, данные сверяются, и только потом чтение переключается на новое. На каждом шаге до последнего можно вернуться назад.