segfault

записки о бэкенде, базах и отладке

16.09.2026 · базы данных

Как я полдня искал N+1, которого не было

Ручка списка заказов тормозила, и я был уверен, что виноват классический N+1: на каждый заказ отдельный запрос за пользователем. Включил лог запросов, приготовился ловить сотни строк — а там их было три.

Проблема оказалась в одном из этих трёх. Запрос за позициями заказов возвращал десятки тысяч строк, потому что джойн потерял условие по дате и тянул всю историю. Приложение потом честно фильтровало это в памяти. То есть база и сеть работали, а время утекало на сериализацию того, что всё равно выбрасывалось.

-- было: план показывал Seq Scan на миллионы строк
EXPLAIN ANALYZE
SELECT * FROM order_items oi
JOIN orders o ON o.id = oi.order_id
WHERE o.user_id = 42;
-- забыто: AND o.created_at >= now() - interval '30 days'

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

postgresqlпроизводительностьотладка
02.09.2026 · надёжность

Таймаут по умолчанию — это бесконечность

Большинство HTTP-клиентов, если не задать таймаут явно, ждут ответа вечно. В нормальный день этого не видно. Проблема всплывает, когда внешний сервис начинает отвечать медленно, но не падает: соединения копятся, пул исчерпывается, и через минуту лежит уже твой сервис, а не чужой.

Любой вызов по сети может зависнуть. Если ты не решил, сколько готов ждать, за тебя это решит худший день в году.

Теперь я завёл правило: у каждого сетевого вызова есть явный таймаут и понятное поведение при его срабатывании. Иногда это ретрай, иногда — отдать кэш, иногда — честно вернуть ошибку. Главное, чтобы это было решением, а не случайностью.

client := &http.Client{
    Timeout: 3 * time.Second, // не оставляем на самотёк
}
сетинадёжностьgo
21.08.2026 · практика

Логи, которые не жаль читать в три ночи

Хороший лог пишется не для того момента, когда всё работает, а для того, когда что-то сломалось и ты смотришь на него первый раз за полгода, невыспавшийся и без контекста. С этой мыслью я и стал их писать иначе.

Три вещи, которые помогли больше всего:

1. Один идентификатор запроса через все сервисы —
   иначе события не собрать в цепочку.
2. Логировать не «что-то пошло не так»,
   а конкретные значения: id, статус, длительность.
3. Уровни всерьёз: ERROR — то, на что будят человека.
   Всё остальное — INFO или ниже.

С тех пор разбор инцидентов стал занимать минуты, а не часы. Никакой магии — просто логи наконец отвечают на вопрос «что произошло», а не «что-то произошло».

наблюдаемостьэксплуатация
05.08.2026 · мнение

В защиту скучных технологий

За последние годы я всё реже выбираю новое и всё чаще — проверенное. Не потому, что новое плохое, а потому что у скучных инструментов есть недооценённое свойство: про них уже всё написано. Любая ошибка, с которой ты столкнёшься, скорее всего, восемь лет назад разобрана в чьём-то ответе на форуме.

Новизну я теперь трачу осознанно: беру одну незнакомую технологию на проект, а не пять сразу. Тогда, если что-то ломается, я хотя бы знаю, где именно искать причину.

архитектурамнение

Об авторе

Бэкенд-инженер, пишу в основном на Go и Python, живу где-то между базой данных и очередью сообщений. Этот блог — место, куда я складываю разобранные баги и выводы, чтобы не наступать на те же грабли дважды.

Всё здесь — личный опыт и личное мнение, а не истина в последней инстанции. Пишу, когда есть о чём.

Архив

2026: сентябрь · сентябрь · август · август