Структура технической статьи для Хабра

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

// промпт
Ты — редактор технических текстов, который много лет читает Хабр и знает, за что там минусуют. Ты не льстишь автору: если тема не тянет на статью, говоришь прямо. Ты понимаешь, что аудитория Хабра проверяет утверждения и не прощает пересказ документации, выданный за опыт. Собери структуру статьи. **Параметры** - О чём статья: {{tema_stati}} - Что я реально сделал своими руками: {{moi_opyt}} - Кто целевой читатель: {{citatel}} - Технологии и версии: {{stek}} - Что читатель должен унести с собой: {{glavnyi_vyvod}} **Как действовать** 1. Сначала честно оцени тему. Хабру не нужен пересказ официальной документации и не нужен рассказ «как я установил популярный фреймворк». Если материал именно такой — скажи об этом первой строкой и предложи, какой поворот сделает его интересным: неочевидные грабли, замеры, сравнение вариантов, отрицательный результат. 2. Определи жанр: разбор проблемы, туториал, постмортем, сравнение решений, исследование с замерами. От жанра зависит вся структура, поэтому выбери один и обоснуй. 3. Придумай заход на 3–5 предложений. На Хабре работает конкретная проблема с цифрой или неожиданный факт, не работает — «в современном мире всё чаще». Дай два варианта захода на выбор. 4. Разложи основную часть на разделы. Для каждого укажи: что в нём происходит, какой артефакт его подкрепляет (код, схема, график, лог, замер) и сколько примерно абзацев он требует. 5. Отдельно помечай места, где нужны мои цифры и детали: версии, конфигурация железа, время выполнения до и после, размер данных. Без них статья читается как теория. 6. Предупреди о типичной реакции комментариев: что спросят, к чему придерутся, какой аргумент стоит закрыть заранее прямо в тексте. 7. Предложи заголовок — три варианта, без кликбейта и без слова «полное руководство». **Формат ответа** Сначала вердикт по теме в двух предложениях, затем жанр, затем варианты захода, затем структура по разделам, затем список того, что нужно добрать от меня. Если материала на статью не хватает — скажи это прямо и предложи формат поменьше.
Заполните переменные

Пример запуска

Сгенерировано Claude Opus 5.5, 24 сентября 2026 г.

Значения переменных

Тема статьи
Как мы заменили Celery + Redis на очередь задач поверх PostgreSQL (SKIP LOCKED) в проде и что из этого вышло
Мой опыт
За три месяца перевёл фоновые задачи биллингового сервиса (около 40 типов тасков, пиковая нагрузка ~1200 задач/мин) с Celery+Redis на собственный воркер на asyncpg с SELECT ... FOR UPDATE SKIP LOCKED. Сам писал воркер, ретраи, дедупликацию, мониторинг через pg_stat_activity. Снял метрики до/после в течение недели на проде: p95 задержки постановки-в-обработку, потребление памяти Redis, число потерянных задач при рестарте пода. Дважды словил дедлок при батчевой выборке из-за неверного порядка блокировок и один раз потерял задачи из-за autovacuum, который не поспевал за таблицей очереди — оба случая описываю с логами и graf.
Читатель
Backend-разработчики на Python (мидл-синьор), которые уже используют Celery в проде и думают об упрощении инфраструктуры или снижении числа компонентов в стеке
Стек
Python 3.11, Celery 5.3.6, Redis 7.2, PostgreSQL 15.4, asyncpg 0.29, SQLAlchemy 2.0, деплой в Kubernetes 1.28, метрики в Prometheus + Grafana
Главный вывод
Отказ от Celery в пользу очереди на PostgreSQL оправдан не всегда: он снижает число движущихся частей и упрощает эксплуатацию, но требует ручной работы с блокировками, вакуумом и мониторингом, которую Celery закрывает из коробки — решение имеет смысл при небольшом-среднем объёме задач и команде, готовой сопровождать SQL-код, а не как универсальная замена

Структура статьи: очередь задач на PostgreSQL вместо Celery + Redis

Вердикт

Тема тянет на полноценную статью, но только за счёт двух инцидентов и замеров до/после. Статей «очередь на SKIP LOCKED за 50 строк» на Хабре и в англоязычных блогах десятки, и эту часть читатель пролистает. Если сделать ядром объяснение, как работает FOR UPDATE SKIP LOCKED, получите пересказ документации и минусы. Если ядро — дедлок с логами, вакуум с графиком и честная таблица «что потеряли вместе с Celery», это будет одна из лучших статей по теме на русском.

Ещё одно предупреждение: формулировка «потеряли задачи из-за autovacuum» в нынешнем виде не переживёт комментарии. Отстающий вакуум сам по себе строки не удаляет. Он даёт bloat, деградацию планов и рост задержек. Потеря возникает где-то дальше по цепочке: таймаут, lease, логика ретраев, DELETE по условию. Нужно точно описать эту цепочку, иначе первый же комментарий будет «вакуум не теряет данные, у вас баг в коде», и он перечеркнёт доверие к остальному тексту.

Жанр: инженерный разбор миграции (case study с постмортемами)

Почему не остальные варианты:

  • Туториал проиграет документации и готовым библиотекам. Читателю незачем копировать ваш воркер, если есть procrastinate и pgqueuer.
  • Сравнение решений не получится: вы замеряли одну альтернативу, а не пять.
  • Чистый постмортем слишком узок: пропадёт вывод о том, когда это вообще стоит делать.

Case study позволяет выстроить линию «решение → реализация → что сломалось → цифры → когда это оправдано». Это ровно та траектория, которая ведёт к нужному вам нюансированному выводу. Отрицательная часть (инциденты, потерянные фичи Celery) здесь работает как главный аргумент доверия.

Варианты захода

Вариант А: от цифры и неожиданности

Мы убрали Redis из биллинга, и p95 задержки от постановки задачи до начала обработки изменился с [X] до [Y] мс. Через две недели мы потеряли [N] задач, и виноват был не наш код, а autovacuum, который не успевал за таблицей очереди. Ещё раньше мы дважды поймали дедлок на запросе, который во всех статьях про SKIP LOCKED подаётся как «без блокировок». Это история про три месяца жизни с очередью на PostgreSQL: что она дала, что отняла и почему я не стал бы советовать её всем.

Вариант Б: от исходной боли

При каждом рестарте пода Celery-воркера мы теряли [N] задач биллинга, а Redis под очередью съедал [X] ГБ памяти при пиках в 1200 задач в минуту. Задачи и так порождались транзакциями в PostgreSQL, поэтому решение казалось очевидным: держать очередь там же. Оно сработало, но не бесплатно. Вместо конфигурации Celery мы получили сопровождение блокировок, вакуума и мониторинга, и именно об этой цене статья.

Вариант Б сильнее, если вы готовы в тексте показать, что Celery был настроен правильно (см. раздел про комментарии). Иначе он провоцирует ответ «вы просто не включили acks_late».

Структура по разделам

Пометка [ВАШИ ДАННЫЕ] означает место, которое без ваших цифр превращается в теорию.

1. Контекст: сервис, нагрузка и конкретные боли

  • Что происходит: какой биллинг, откуда берутся задачи, 40 типов, пик около 1200 задач/мин (≈20/с, это стоит написать прямо, чтобы не выглядело как хайлоад). Главное — что именно болело в Celery. Формулировка «лишний компонент» не аргумент, нужны инциденты.
  • Артефакт: схема «до» (сервис → Redis → воркеры → PG) и таблица типов задач по частоте и длительности.
  • Объём: 3 абзаца.
  • [ВАШИ ДАННЫЕ]: распределение длительности задач (p50/p95/max), доля самых частых типов, размер payload, число подов воркеров, ресурсы PG (vCPU, RAM, диск, managed или свой), конфиг Celery (acks_late, visibility_timeout, prefetch_multiplier, task_reject_on_worker_lost).

2. Почему не готовое решение

  • Что происходит: честный разбор альтернатив. Без этого раздела статью закидают вопросами «зачем велосипед».
  • Артефакт: таблица «вариант — почему не подошёл»: донастроить Celery; Celery с брокером RabbitMQ; Dramatiq; procrastinate; pgqueuer; pgmq; outbox поверх существующего Celery.
  • Объём: 2 абзаца плюс таблица.
  • Внимание: если вы готовые PG-очереди не рассматривали, так и напишите и объясните, почему сейчас выбрали бы или не выбрали бы их. Попытка это скрыть видна сразу.

3. Дизайн очереди

  • Что происходит: схема таблицы, индексы, запрос выборки. Ключевое архитектурное решение здесь — модель владения задачей:

    • держим row lock на время выполнения задачи (открытая транзакция, риск idle in transaction);
    • или lease-модель: status = running, locked_until, реклейм протухших.

    Обязательно покажите, ставится ли задача в той же транзакции, что и бизнес-изменение. Если да, это главный аргумент в пользу PG-очереди, и его надо поднять наверх. Если нет, комментаторы спросят, зачем вообще PG.

  • Артефакт: DDL таблицы с индексами (частичный индекс по status = 'pending'), запрос выборки целиком (CTE + UPDATE ... RETURNING), схема жизненного цикла задачи.

  • Объём: 4 абзаца. Механику SKIP LOCKED уложите в 1 абзац со ссылкой на документацию.

  • [ВАШИ ДАННЫЕ]: размер батча и почему именно такой; как будите воркеры (polling с интервалом или LISTEN/NOTIFY); настройки пула asyncpg; используется ли PgBouncer и в каком режиме.

4. Ретраи, дедупликация, таймауты

  • Что происходит: backoff, максимум попыток, dead-letter, дедупликация через уникальный (частичный) индекс по ключу идемпотентности. Отдельно: семантика at-least-once и как вы делаете хендлеры идемпотентными. Для биллинга это вопрос номер один.
  • Артефакт: код ретрая и INSERT ... ON CONFLICT DO NOTHING для дедупликации.
  • Объём: 3 абзаца.
  • [ВАШИ ДАННЫЕ]: сколько дублей отсекает дедупликация за сутки; что происходит с задачей, которая падает по таймауту в середине списания.

5. Миграция без остановки

  • Что происходит: как переводили 40 типов за три месяца: по одному типу, фиче-флаги, двойная запись, откат.
  • Артефакт: таймлайн миграции (какие типы когда), схема переключения.
  • Объём: 2 абзаца.
  • [ВАШИ ДАННЫЕ]: были ли откаты; какой тип задач переводили первым и почему.

6. Инцидент 1: дедлоки при батчевой выборке

  • Что происходит: хронология, лог, разбор. Нужно точно показать, какие именно блокировки брались в разном порядке. Сам SELECT ... FOR UPDATE SKIP LOCKED со своими строками дедлок не создаёт, потому что занятые строки пропускает. Значит, дедлок возникал на следующих шагах: UPDATE в другом порядке, внешние ключи, блокировки связанных строк биллинга, пакетный UPDATE без ORDER BY. Это самый ценный раздел статьи.
  • Артефакт: фрагмент лога deadlock detected с DETAIL (процессы, запросы, объекты). Код «было / стало». При возможности — воспроизведение на двух psql-сессиях.
  • Объём: 4 абзаца.
  • [ВАШИ ДАННЫЕ]: точный текст ошибки, частота, что происходило с задачами в момент дедлока (ретрай сработал или нет), как вы нашли причину.

7. Инцидент 2: autovacuum не успевает за очередью

  • Что происходит: очередь — это антипаттерн для MVCC: постоянные insert/update/delete порождают мёртвые кортежи. Нужна полная цепочка: рост n_dead_tup → bloat таблицы и индекса → выборка деградирует → [что именно привело к потере задач]. Затем что мешало вакууму: дефолтные пороги, долгая транзакция, держащая xmin horizon (аналитический запрос, idle in transaction, реплика с hot_standby_feedback, слот репликации). И что сделали.
  • Артефакт: график Grafana с наложением n_dead_tup, размера таблицы и p95 задержки. Лог autovacuum (log_autovacuum_min_duration). Итоговые per-table настройки autovacuum. Если было — переход на партиционирование с DROP/TRUNCATE старых партиций или вынос завершённых задач в архивную таблицу.
  • Объём: 5 абзацев.
  • [ВАШИ ДАННЫЕ]: сколько задач потеряно и как это обнаружили, пиковые значения мёртвых кортежей и размера таблицы, значения autovacuum_vacuum_scale_factor, autovacuum_vacuum_cost_limit и fillfactor до и после, доля HOT-updates из pg_stat_user_tables, как восстанавливали потерянные задачи.

8. Мониторинг, который пришлось написать самим

  • Что происходит: что Celery/Flower давал бесплатно и что вы воспроизвели сами: глубина очереди по типам, возраст самой старой pending-задачи, число running с истёкшим lease, ожидания блокировок и idle in transaction из pg_stat_activity, мёртвые кортежи. Какие алерты реально сработали за эти месяцы.
  • Артефакт: SQL-запросы для экспортёра, скриншот дашборда, правила алертов.
  • Объём: 3 абзаца.
  • [ВАШИ ДАННЫЕ]: сколько человеко-дней ушло на мониторинг; какие алерты оказались шумными.

9. Замеры до и после

  • Что происходит: методология и результаты. Методология важнее цифр: неделя «до» и неделя «после» — разные недели с разной нагрузкой. Нормализуйте по количеству задач, покажите сопоставимость периодов.

  • Артефакт: таблица метрик «до / после»:

    • p50/p95/p99 задержки от постановки до начала обработки;
    • память Redis;
    • нагрузка на PG: CPU, IOPS, WAL в сутки, число соединений;
    • потерянные задачи при рестарте пода;
    • число компонентов в стеке.

    К таблице — график задержки за обе недели.

  • Объём: 3 абзаца плюс таблица.

  • [ВАШИ ДАННЫЕ]: все цифры таблицы; как именно измеряли потери при рестарте (контролируемые рестарты? сколько раз?); как измеряли задержку (timestamp постановки в задаче vs время старта). Обязательно покажите, что стало хуже. Рост WAL и нагрузки на основную базу почти наверняка есть.

10. Что мы потеряли вместе с Celery

  • Что происходит: честный список: beat/периодические задачи, canvas (chain/chord/group), rate limit по типу задач, ETA/countdown, Flower, приоритеты, экосистема, найм («Celery знают все, наш воркер — двое»). По каждому пункту: сделали сами, отказались или живём без него.
  • Артефакт: таблица «фича — статус».
  • Объём: 2 абзаца плюс таблица.

11. Когда это стоит делать, а когда нет

  • Что происходит: главный вывод в виде чеклиста.
    • Имеет смысл: задачи порождаются транзакциями в той же БД; нагрузка десятки задач в секунду, а не тысячи; есть человек, который понимает MVCC и блокировки; не нужны сложные workflow.
    • Не имеет смысла: очередь сильно больше этого масштаба; PG и так на пределе; нужны chord/chain; команда без экспертизы в PG.
  • Артефакт: чеклист или дерево решений.
  • Объём: 2 абзаца плюс список.
  • Внимание: не называйте порог масштаба, который вы не проверяли. Вы жили на ~20 задачах/с. Если хотите написать «до N задач/с нормально», сделайте нагрузочный тест на копии и найдите, где начинается деградация. Это усилит статью, но не обязательно. Без теста честно напишите: «проверено на нашем масштабе, выше — не знаю».

Итого: около 35 абзацев плюс код, таблицы и 3–4 графика. Это длинная статья, но для Хабра нормальная. Если придётся резать — сокращайте разделы 4 и 5, а не инциденты.

Что скажут в комментариях и что закрыть в тексте

  1. «Вы просто неправильно настроили Celery». Про потери при рестарте спросят в первую очередь. Покажите конфиг с acks_late=True, task_reject_on_worker_lost=True и visibility_timeout, либо честно признайте, что не был настроен, и объясните, почему не стали чинить.
  2. «Зачем велосипед, есть procrastinate / pgqueuer / pgmq». Закрывается разделом 2.
  3. «1200 в минуту — это 20 в секунду, это не нагрузка». Напишите это сами в разделе 1, раньше комментаторов. Тогда это не слабость, а честное позиционирование.
  4. «Нагрузили основную базу биллинга очередью». Покажите метрики PG после миграции: CPU, WAL, соединения. Скажите, одна это база или отдельный инстанс.
  5. «Autovacuum не теряет задачи». Опишите точную цепочку потери (см. вердикт).
  6. «SKIP LOCKED не даёт дедлоков». Точно покажите, где брались конфликтующие блокировки.
  7. «asyncpg + PgBouncer в transaction mode ломают prepared statements». Если используете PgBouncer, упомяните statement_cache_size=0 или аналогичное решение. Если не используете, объясните, как живёте с числом соединений.
  8. «Почему не LISTEN/NOTIFY» или наоборот «NOTIFY не масштабируется». Одна фраза о выборе.
  9. «Что с exactly-once в биллинге?» Идемпотентность хендлеров из раздела 4 должна быть явной.
  10. «Бас-фактор». Кто сопровождает воркер, если вы уйдёте. Одного честного абзаца в разделе 10 достаточно.

Заголовок

  1. «Убрали Celery и Redis из биллинга: очередь на PostgreSQL, два дедлока и один autovacuum»
  2. «Очередь задач на PostgreSQL SKIP LOCKED в проде: три месяца, замеры и цена отказа от Celery»
  3. «Когда очередь в PostgreSQL лучше Celery, а когда нет: опыт миграции биллингового сервиса»

Первый лучше остальных: конкретика и честный намёк на проблемы, без кликбейта.

Что нужно добрать от вас

Контекст

  • Ресурсы и развёртывание PostgreSQL 15.4: железо или managed, vCPU/RAM, тип диска; одна база с биллингом или отдельная; есть ли реплики.
  • Конфиг Celery 5.3.6 до миграции (acks_late, visibility_timeout, prefetch_multiplier, reject_on_worker_lost), число воркеров и concurrency.
  • Распределение длительности задач и размер payload.
  • Рассматривали ли готовые PG-очереди и почему отказались.

Реализация

  • DDL таблицы и индексов, запрос выборки целиком.
  • Модель владения задачей: lock на всё время выполнения или lease.
  • Ставятся ли задачи в той же транзакции, что и бизнес-операция.
  • Polling или LISTEN/NOTIFY; размер батча; пул asyncpg; PgBouncer.
  • Как устроены идемпотентность хендлеров и дедупликация.

Инциденты

  • Логи дедлоков с DETAIL, код до и после исправления.
  • Точная цепочка потери задач при проблеме с вакуумом, число потерянных задач, способ обнаружения и восстановления.
  • Графики n_dead_tup, размера таблицы и задержки за период инцидента; настройки autovacuum до и после; кто держал xmin horizon, если держал.

Замеры

  • Сопоставимость недель «до» и «после»: объём задач, нормализация.
  • Цифры для таблицы: p50/p95/p99 задержки, память Redis, CPU/IOPS/WAL/соединения PG, потери при рестарте, методика их подсчёта.
  • Метрики, которые стали хуже. Обязательно хотя бы одна.

Итог

  • Какие фичи Celery заменили сами, от каких отказались.
  • Трудозатраты: три месяца — это ваше полное время или параллельно с другой работой; сколько ушло на мониторинг и разбор инцидентов.
  • Будете ли вы делать это снова и что сделали бы иначе. Один абзац честного ответа в финале стоит больше всего чеклиста.

Похожие промпты

Социальные сети и Коммуникация

Постмортем инцидента для публикации

Превращает внутренний разбор аварии в публичный постмортем: хронология, настоящая причина вместо «человеческого фактора», выводы без самобичевания и без корпоративного тумана.

Социальные сети и Коммуникация

Разбор дискуссии в треде: аргументы сторон

Разбирает длинный спор в X: кто что утверждает, какие аргументы опираются на факты, где стороны спорят о разном и в чём они на самом деле согласны.

Социальные сети и Коммуникация

Анализ трендов в X по теме

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

Социальные сети и Коммуникация

Вирусные посты для Telegram-канала

Пишет посты для Telegram-канала с высоким потенциалом пересылок: цепляющие первые строки, проверенные виральные форматы и призывы, которые запускают репосты.