Зачем платить $1200 в месяц за оркестратор, если хватает одной таблицы в PostgreSQL
Управляемый workflow-сервис для стартапа стоит от $1200 в месяц, и за эти деньги вам продают очередь задач с ретраями плюс дашборд, на который вы будете смотреть раз в неделю. Всё то же самое умеет PostgreSQL, который у вас уже развёрнут. Плюс 200 строк на FastAPI. Всё.
Моя позиция: до десятков миллионов строк в таблице задач Kafka в этом стеке не нужна. Celery тоже.
Схема простая. Одна таблица tasks: id (UUID), type, payload в JSONB, status, attempt, locked_until, таймстемпы. Никаких брокеров.
Гонки между воркерами снимает одна SQL-конструкция: SELECT ... FOR UPDATE SKIP LOCKED. Воркер захватывает строку, конкуренты её молча пропускают и берут следующую свободную, и никто никого не ждёт. Это встроено в PostgreSQL с версии 9.5. С 2016 года. Почему-то половина команд до сих пор об этом не знает и тащит RabbitMQ в проект из трёх сервисов.
Статусы: pending, потом running, потом completed. Упавшая задача уходит в failed и возвращается в pending со счётчиком attempt. Идемпотентность держится на processed_at и уникальном ключе операции, поэтому повторный запуск той же задачи ничего не ломает, сколько бы раз воркер ни умирал посреди работы.
API поверх этого умещается в четыре эндпоинта. POST /tasks ставит задачу. GET /tasks/{id} отдаёт статус. Есть отмена. Есть листинг с фильтрами, он же дашборд. Наблюдаемость сводится к обычным SQL-запросам по той же таблице: сколько задач висит в pending дольше пяти минут, показывает один SELECT, а в managed-сервисе это вкладка, за которую вы платите.
Такая конструкция на скромной машине переваривает десятки тысяч задач в час с субсекундной задержкой. Когда таблица дорастёт до десятков миллионов строк, придёт время партиционирования. Не раньше.
Тест на переусложнение у меня один. Если первую рабочую версию нельзя собрать за выходные, архитектура уже переусложнена.
Полный разбор со схемой таблицы и кодом: https://anipers.com/media/fastapi-control-plane