Привет. Меня зовут Даниил Дулин, и это канал про backend без воды.
15 лет пишу и проектирую серверные системы. За плечами:
— Ozon Bank — микрокредитная система, финтех на Go — Wildberries — складская логистика, миллионы операций — Minter — 5 лет в блокчейн-стартапе, открытое API — X5 — e-commerce под нагрузкой
Сейчас веду консалтинговую практику dulin.pro (аудит, архитектура, экспертиза) и команду инженеров на Go dulin.tech.
О чём здесь будет:
— архитектура highload-систем — без слайдов «как у больших», а как это работает на самом деле — Go в продакшене: паттерны, грабли, решения — финтех и платежи: идемпотентность, реконсиляция, распределённые транзакции — миграции legacy → Go без даунтайма — разборы реальных кейсов с цифрами, а не «всё получилось»
Без инфоцыганства, без «10 секретов сеньора», без пересказа документации. Только то, что проверено руками в проде.
Если у вас есть задача на backend или архитектуру — пишите: hello@dulin.tech или лично @daniildulin. Первый созвон бесплатный.
Добро пожаловать 👋
15 лет пишу и проектирую серверные системы. За плечами:
— Ozon Bank — микрокредитная система, финтех на Go — Wildberries — складская логистика, миллионы операций — Minter — 5 лет в блокчейн-стартапе, открытое API — X5 — e-commerce под нагрузкой
Сейчас веду консалтинговую практику dulin.pro (аудит, архитектура, экспертиза) и команду инженеров на Go dulin.tech.
О чём здесь будет:
— архитектура highload-систем — без слайдов «как у больших», а как это работает на самом деле — Go в продакшене: паттерны, грабли, решения — финтех и платежи: идемпотентность, реконсиляция, распределённые транзакции — миграции legacy → Go без даунтайма — разборы реальных кейсов с цифрами, а не «всё получилось»
Без инфоцыганства, без «10 секретов сеньора», без пересказа документации. Только то, что проверено руками в проде.
Если у вас есть задача на backend или архитектуру — пишите: hello@dulin.tech или лично @daniildulin. Первый созвон бесплатный.
Добро пожаловать 👋
Небольшой пост #1 — про SELECT перед INSERT
---
«SELECT перед INSERT» — это не проверка уникальности. Это иллюзия проверки.
Вижу этот паттерн в каждом втором проекте:
На стенде работает идеально. В проде раз в неделю появляется дубль, который никто не может воспроизвести.
Причина простая: между
Уникальность под конкурентной нагрузкой умеет гарантировать только БД. Не код приложения.
Нарушение constraint — не баг, а штатная ситуация, которую нужно обработать.
Правило: если корректность зависит от того, что между двумя запросами в БД никто не влезет, — она от этого уже не зависит. Кто-нибудь да влезет.
---
«SELECT перед INSERT» — это не проверка уникальности. Это иллюзия проверки.
Вижу этот паттерн в каждом втором проекте:
if !exists(key) {
insert(key, data)
}На стенде работает идеально. В проде раз в неделю появляется дубль, который никто не может воспроизвести.
Причина простая: между
exists() и insert() есть зазор. Два параллельных запроса оба проходят проверку «записи нет», оба делают INSERT. Получили два. Чем выше нагрузка — тем чаще.Уникальность под конкурентной нагрузкой умеет гарантировать только БД. Не код приложения.
CREATE UNIQUE INDEX idx_key ON table (key);
err := repo.Insert(ctx, data)
if isUniqueViolation(err) {
return existing, nil // это не ошибка — это второй ретрай
}
Нарушение constraint — не баг, а штатная ситуация, которую нужно обработать.
Правило: если корректность зависит от того, что между двумя запросами в БД никто не влезет, — она от этого уже не зависит. Кто-нибудь да влезет.
