57 / QUEUES & WORKERS / PRODUCTION FABRIC
57 / PRODUCTION / WORK UNITS · LEASES · ACK · RETRY · CONCURRENCY

QUEUES
& WORKERS.

Queue — durable или operational backlog единиц работы, ожидающих выполнения. Worker — исполнитель, который забирает допустимую работу, выполняет её в ограниченном контексте и фиксирует результат.

Главный принцип: очередь отделяет момент создания работы от момента и места выполнения. Это позволяет переживать пики нагрузки, временные сбои и рестарты, ограничивать concurrency и масштабировать исполнение независимо от request path.
00. ARCHITECTURAL STATUS

ОЧЕРЕДЬ НУЖНА, КОГДА РАБОТА НЕ ДОЛЖНА ЖИТЬ ВНУТРИ ОДНОГО HTTP-ЗАПРОСА

Для простой локальной AI-системы многие операции можно выполнять синхронно. Queue/worker слой появляется, когда задачи долгие, bursty, resource-heavy, retryable, asynchronous или должны переживать restart процесса.
TYPEPRODUCTIONAsynchronous execution infrastructure.
DEFAULTCONDITIONALНе нужен для каждого вызова.
ENABLE WHENASYNC / DURABLE WORKLong-running, bursty, retryable, background work.
SEPARATE COMPONENTYESLogical/runtime responsibility.
LIVES INPRODUCTION FABRICSupporting infrastructure, не новый cognitive module.
COMPLEXITYLOW → HIGHPostgreSQL queue may be enough.
IMPLEMENT: WHEN ASYNC PAYS OFF
Минимум 80% ценности: versioned job contract, READY→LEASED lifecycle, visibility/lease timeout, idempotent handler, bounded retries, dead-letter state, concurrency caps, graceful worker shutdown, queue age/depth metrics и explicit tenant/priority. Не нужен Kafka/RabbitMQ «потому что production» — PostgreSQL + workers часто достаточно.
01A. ARCHITECTURE BOUNDARIES & OPERATIONS

EXPLICIT SYSTEM CONTRACT

A. BOUNDARY WITH NEIGHBORS

№42 Events & Triggers определяет смысл события и реакцию; №57 хранит/исполняет resulting work unit. №58 Scheduler создаёт сигнал/работу по времени; queue исполняет её, когда есть capacity. №59 Broker / Message Bus транспортирует сообщения/pub-sub между producers/consumers; №57 фокусируется на work backlog, claim/lease/ack. №63 Retry & Circuit Breakers позже владеет общей resilience policy; №57 реализует базовые retry/redrive semantics конкретной работы. №68 Durable Workflow хранит историю и состояние многошагового процесса; queue лишь доставляет отдельные activity/work units. №69 Distributed Reliability синтезирует delivery/idempotency/locks/DLQ на системном уровне.

B. PREREQUISITES / CROSS-REFERENCES

Prerequisites: №10 State Management, №42 Events, №46 Observability, №50 Contracts, №55 Ingestion & Sync. Forward references: №58 Scheduler, №59 Broker, №60 Artifact Store, №63 Retry/Circuit Breakers, №64 Rate Limits/Budgets, №68 Durable Workflow, №69 Distributed Reliability.

C. PLANE PLACEMENT

REQUEST-TIME: producer может enqueue и сразу вернуть task/job reference. CONTROL PLANE: queue definitions, worker pools, concurrency, priorities, retry/dead-letter rules. DATA PLANE: job envelopes, leases, results/status. OFFLINE: re-drive, maintenance, capacity analysis, load/failure tests.

D. FAILURE & OPERATIONS CONTRACT

Success: one logical work item eventually reaches terminal success or explicit terminal failure. Retryable: transient worker/tool/provider failures. Permanent: invalid contract, permission/policy deny, deterministic unsupported input. Delivery: assume at-least-once unless proven otherwise. Idempotency: handler/effect key required for repeat delivery. Persist: job_id, payload ref/version, attempts, lease owner/expiry, status, result/error refs, timestamps. Trace: enqueue→claim→attempt→result/retry/dead.

E. WHAT THIS TOPIC DOES NOT OWN

№57 не владеет business event semantics, calendar/time scheduling, pub-sub topology, workflow history/replay, global retry/circuit policy или artifact/blob storage. Она владеет THE LIFECYCLE OF EXECUTABLE WORK UNITS AND THE WORKERS THAT CLAIM THEM.

01. WHY A QUEUE

РАЗВЯЗАТЬ PRODUCER И EXECUTOR

WITHOUT QUEUE

HTTP/user flow ждёт OCR, ingestion, embeddings, export или long tool call.

Crash = работа потеряна, spike = request storm.

QUEUE

Producer durable записывает work item и получает job_id.

Backlog становится наблюдаемым и управляемым.

WORKER POOL

Workers забирают столько работы, сколько система способна безопасно выполнить.

Queue — это не способ сделать работу быстрее. Она делает нагрузку управляемой, переживаемой и масштабируемой, иногда ценой дополнительной latency.
02. GOOD QUEUE USE CASES

ЧТО СТОИТ ВЫНОСИТЬ ИЗ REQUEST PATH

INGESTION

Documents / source objects

Fetch, parse, chunk, embed, reindex — естественные background work units.

LONG TOOLS

Expensive operations

Exports, conversions, browser jobs, large research stages, sandbox tasks.

BURSTY EVENTS

Smooth spikes

1000 webhook events приходят за минуту; workers обрабатывают с controlled concurrency.

RETRYABLE I/O

External systems

Provider temporarily unavailable; job waits/retries independently of user connection.

BATCH

Parallel work units

Page parsing, embedding chunks, evaluation cases, fan-out jobs.

DEFERRED SIDE TASK

Non-blocking

Analytics, audit enrichment, thumbnails, secondary indexes where consistency allows.

03. WHEN NOT TO QUEUE

НЕ ПРЕВРАЩАТЬ КАЖДУЮ ФУНКЦИЮ В DISTRIBUTED JOB

FAST LOCAL

Just call it

10–100 ms deterministic transform внутри одного процесса не выигрывает от queue hop.

STRICT IMMEDIATE RESULT

User needs answer now

Если operation короткая и result нужен для продолжения request, synchronous call проще.

TINY SYSTEM

One process

Пока workload мал, обычная function + persisted state может быть лучше дополнительной инфраструктуры.

Asynchrony — это сложность: job states, retries, observability, consistency, duplicate delivery. Включать её там, где она решает реальную operational problem.
04. JOB CONTRACT

QUEUE ДОЛЖНА ХРАНИТЬ WORK UNIT, А НЕ «КАКОЙ-ТО JSON»

{
  "contract": "job.v1",
  "job_id": "JOB-...",
  "job_type": "document.parse",
  "tenant_id": "tenant_A",
  "payload": {
    "source_ref": "doc://...",
    "parser_profile": "documents.v2"
  },
  "priority": 50,
  "idempotency_key": "parse:doc123:v42:p2",
  "attempt": 0,
  "max_attempts": 4,
  "timeout_s": 120,
  "not_before": null,
  "trace_id": "TRACE-...",
  "created_at": "...",
  "contract_version": "1.0"
}
JOB ENVELOPE

Control data outside payload

Минимально полезны:

  • stable job_id;
  • job_type + contract version;
  • tenant/security context reference;
  • idempotency key;
  • priority;
  • attempt/max attempts;
  • timeout;
  • trace/correlation id;
  • payload или payload_ref.

Worker не должен угадывать retry semantics из текста payload.

05. LARGE PAYLOADS

QUEUE — НЕ ARTIFACT STORE

BAD

Put blob in job

200 MB PDF, full trace или giant model context копируется в message/job row и на каждый retry.

BETTER

Pass references

Queue хранит artifact_ref, source_ref, state_ref + version/hash. №60 Artifact Store хранит bytes.

Job payload должен быть маленьким, сериализуемым и устойчивым к retry. Крупные immutable inputs/outputs передаются references.
06. JOB STATE MACHINE

РАБОТА — ЭТО ЯВНЫЙ LIFECYCLE

READY

Можно claim, если not_before прошёл и queue/policy допускает.

LEASED

Worker получил временное право выполнить job.

RUNNING

Attempt выполняется; heartbeat может продлевать lease.

SUCCEEDED

Terminal success; result persisted.

RETRY_WAIT

Retryable failure; next_attempt_at установлен.

DEAD

Attempts exhausted / poison / manual intervention.

CANCELLED

Работа больше не должна исполняться.

READY
  ↓ claim atomically
LEASED / RUNNING
  ├─ success ───────────────→ SUCCEEDED
  ├─ retryable failure ─────→ RETRY_WAIT → READY
  ├─ permanent failure ─────→ DEAD
  ├─ attempts exhausted ────→ DEAD
  ├─ cancel requested ──────→ CANCELLED / cooperative stop
  └─ worker disappears
          ↓ lease expires
        READY again
Lease expiry — ключ к crash recovery: если worker умер после claim, job не должна навсегда остаться «RUNNING».
07. LEASE / VISIBILITY TIMEOUT

WORKER НЕ «ЗАБИРАЕТ НАВСЕГДА» — ОН АРЕНДУЕТ JOB

CLAIM

Atomic lease

Worker atomically marks job leased by worker_id until lease_until.

HEARTBEAT

Extend if alive

Для длинного job worker может продлевать lease, но не бесконечно без upper bounds.

EXPIRE

Recover crash

Если heartbeat исчез, job снова становится claimable.

DUPLICATE WINDOW
Worker A мог совершить side effect, затем потерять lease до ACK. Worker B получит ту же job. Поэтому lease не заменяет idempotency: внешние эффекты должны иметь operation/idempotency key или read-before-write semantics.
08. ACK / NACK

DELIVERY ЗАКАНЧИВАЕТСЯ ТОЛЬКО ПОСЛЕ DURABLE RESULT

ActionMeaningWhen
ACK / SUCCESSRequired effects and result state are durable.Job becomes SUCCEEDED.
NACK / RETRYAttempt failed transiently.Increment attempt, calculate next_attempt_at.
FAIL PERMANENTSame input will not succeed unchanged.DEAD / terminal error; no blind retries.
ABANDONWorker lost/crashed without final transition.Lease expiry makes job visible again.
Не ACK-ать job перед записью результата «для скорости». Crash после раннего ACK создаёт тихую потерю работы.
09. DELIVERY SEMANTICS

AT-LEAST-ONCE — ПРАКТИЧЕСКИЙ DEFAULT

MODEL
LOSS RISK
DUP RISK
HANDLER
COMPLEXITY
PRACTICAL USE
AT-MOST-ONCE
possible
low
simple
LOW
Only disposable/noncritical work.
AT-LEAST-ONCE
low if durable
expected
must be idempotent
MEDIUM
Best default for jobs.
EXACTLY-ONCE EFFECT
desired
desired
requires transactional/idempotent design
HIGH
Achieve at effect boundary, not by slogan.
«Queue guarantees exactly once» почти никогда не избавляет от проверки side effects. Реальная цель — exactly-once logical effect через idempotency, unique constraints, transactional outbox/inbox или provider keys там, где это нужно.
10. IDEMPOTENT WORKER

ОДИН JOB МОЖЕТ ЗАПУСТИТЬСЯ ДВАЖДЫ — РЕЗУЛЬТАТ НЕ ДОЛЖЕН УДВОИТЬСЯ

handle(job):
    validate_contract(job)

    prior = lookup_effect(job.idempotency_key)
    if prior.completed:
        return prior.result

    input = load_refs(job.payload)

    result = execute_deterministically(input)

    persist_result(
        idempotency_key=job.idempotency_key,
        result=result
    )

    return result
IDEMPOTENCY PATTERNS

Choose by effect

  • Unique constraint on logical key.
  • Upsert by source/version.
  • Provider idempotency key.
  • Compare-and-set expected version.
  • Read-before-write where authoritative.
  • Result table keyed by job/effect key.

«Мы никогда не доставим job дважды» — слабый invariant.

11. RETRIES

RETRY ДОЛЖЕН БЫТЬ РЕШЕНИЕМ ПО ERROR CLASS

ErrorRetry?Typical behavior
Network timeout / transient 5xxYESExponential backoff + jitter, bounded attempts.
Rate limitedYES, laterHonor Retry-After / reduce concurrency.
Invalid input schemaNO unchangedPermanent fail / producer repair.
Permission / policy deniedNO unchangedDo not retry to bypass security.
Version conflictCONDITIONALReload current state and re-evaluate.
Model/provider quality failureCONDITIONALOnly if repair/escalation policy expects improvement.
№63 позже систематизирует Retry/Fallback/Circuit Breakers. Здесь invariant: queue должна различать retryable и permanent failures и не создавать бесконечный poison loop.
12. DEAD-LETTER / POISON JOBS

НЕПРОХОДИМАЯ JOB НЕ ДОЛЖНА БЕСКОНЕЧНО ЗАНИМАТЬ WORKER

POISON

Always fails

Corrupt file, unsupported schema, deterministic bug, missing permission.

DEAD

Terminal holding state

После max attempts/permanent error job переводится в DEAD с structured error.

REDRIVE

Manual/controlled replay

После исправления code/config/input можно создать new attempt/redrive с audit trail.

Dead-letter queue/state — не мусорная корзина. Для неё нужны ownership, alerting, inspection и controlled re-drive procedure.
13. BACKPRESSURE

QUEUE ПОКАЗЫВАЕТ, ЧТО PRODUCERS БЫСТРЕЕ CONSUMERS

PRODUCERS events / uploads user requests sync jobs QUEUE OLDEST AGE ↑ WORKERS bounded concurrency resource-aware autoscale if useful
ABSORB

Short burst

Queue grows temporarily; workers catch up without overloading downstream.

THROTTLE

Sustained overload

Admission control, producer rate reduction, lower priority shedding, quotas.

SCALE

If downstream allows

Add workers only if provider/DB/CPU quotas can absorb more concurrency.

Queue depth alone can mislead. Oldest job age and arrival-vs-completion rate usually better show whether system actually falls behind.
14. CONCURRENCY

БОЛЬШЕ WORKERS ≠ БОЛЬШЕ THROUGHPUT БЕСКОНЕЧНО

GLOBAL

Total workers

Защищает CPU/RAM/database/shared infrastructure.

PER TYPE

Job class

OCR может иметь concurrency 2, embeddings 16, emails 4.

PER TENANT

Fairness

Один крупный customer не занимает весь worker pool.

PER RESOURCE

External provider

Connector/provider concurrency respects rate and quota limits.

Concurrency должен быть связан с №64 quotas/rate limits. Автоскейлить workers, когда bottleneck — внешний API с quota 10 req/s, бессмысленно.
15. PRIORITY & FAIRNESS

PRIORITY НУЖНА, НО STARVATION НЕЛЬЗЯ СКРЫВАТЬ

MechanismUseRisk
Simple FIFOHomogeneous jobs.Large slow jobs block urgent work.
Priority valueInteractive/high-risk recovery ahead of batch.Low-priority starvation.
Separate queues/poolsDifferent resource classes / SLAs.More operational complexity.
Tenant fair-shareMulti-tenant workloads.Needs explicit fairness policy.
AgingOld low-priority jobs gradually rise.Implementation complexity but prevents starvation.
Priority должна отражать operational/business SLA, а не «модель решила, что её job очень важная». Host/system policy устанавливает allowed priority class.
16. WORKER TYPES

НЕ ОБЯЗАТЕЛЬНО ОДИН УНИВЕРСАЛЬНЫЙ WORKER IMAGE

CPU

Transform worker

Parsing, compression, deterministic processing.

I/O

Connector worker

Network-heavy API calls with controlled concurrency.

GPU / MODEL

Inference worker

Embeddings/local inference jobs with scarce accelerator capacity.

SANDBOX

Isolated execution

Jobs requiring special containment/runtime profiles.

Разделение pools снижает dependency blast radius и позволяет independently tune resources/concurrency. Но не создавать десятки worker services без нагрузки, которая это оправдывает.
17. PULL VS PUSH

КАК WORKER ПОЛУЧАЕТ РАБОТУ

PULL

Worker claims

Worker сам запрашивает next eligible job. Естественно для DB queues и многих task queues; concurrency локально controllable.

PUSH

Queue/broker delivers

Infrastructure вызывает consumer/доставляет message. Требует обработать duplicate delivery, timeout/ack semantics и consumer availability.

Выбор transport не меняет invariants: job contract, idempotency, bounded retry, timeout, observability, access scope и terminal state всё равно нужны.
18. CANCELLATION

«ОТМЕНИЛИ JOB» НЕ ВСЕГДА ОЗНАЧАЕТ «ПРОЦЕСС МГНОВЕННО ИСЧЕЗ»

READY

Easy cancel

Не claim-ить job; transition to CANCELLED.

RUNNING

Cooperative cancel

Worker periodically checks cancellation or receives signal and safely stops at cancellation points.

SIDE EFFECT DONE

Cannot un-happen

Cancellation may require compensating action, not mere process kill.

Hard kill безопасен только если effect boundaries позволяют. Для внешних writes нужно различать «execution cancelled» и «business effect compensated».
19. GRACEFUL SHUTDOWN

DEPLOY НЕ ДОЛЖЕН СЛУЧАЙНО СОЗДАВАТЬ DUPLICATE WORK

STOP CLAIMINGWorker enters draining mode.
FINISH / CHECKPOINTComplete current work if within shutdown budget.
ACK DURABLEPersist result before final success.
RELEASEAbandon/release lease for unfinished jobs.
EXITNo orphan process/state.
Worker lifecycle должен быть deployment-aware: readiness/liveness, drain, lease expiry и hard shutdown должны работать вместе.
20. SECURITY & TENANCY

QUEUE НЕ ДОЛЖНА СТАТЬ ОБХОДОМ PERMISSIONS

PRODUCER

Can enqueue?

Producer authorized for job_type/tenant/resource; queue payload validated.

WORKER

Least privilege

Worker pool получает только capabilities, нужные его job types.

EXECUTION

Re-check current authority

Для sensitive side effects permission/policy may need re-evaluation at execution time, not only enqueue time.

STALE AUTHORITY
Job могла провести час в queue. За это время user lost access, approval expired или resource changed. Sensitive worker не должен считать старый enqueue фактом вечного authorization.
21. OBSERVABILITY

QUEUE HEALTH — ЭТО НЕ ТОЛЬКО «СКОЛЬКО JOBS»

DEPTH

Backlog

Ready/retry/running/dead counts by job type/tenant.

AGE

Oldest job

Лучший сигнал sustained backlog и SLA risk.

WAIT

Queue latency

enqueue_at → start_at p50/p95.

RUN

Execution latency

start_at → terminal result.

RATE

Flow

arrival rate vs completion rate.

RETRY

Attempts

retry distribution and retry causes.

LEASE

Worker health

expired leases / lost workers / heartbeat delays.

DEAD

Poison backlog

Dead jobs count, age, owner, redrive status.

Alerting should usually focus on age/SLA, error rate, dead jobs and sustained arrival>completion, not arbitrary queue depth alone.
22. AUTOSCALING

МАСШТАБИРОВАТЬ ПО ДАВЛЕНИЮ, НО УВАЖАТЬ BOTTLENECK

SignalUseful?Caveat
Queue depthYESNeeds job cost context; 100 tiny != 100 huge.
Oldest ageVERYStrong SLA/backlog signal.
Arrival/completion ratioVERYShows whether backlog will grow.
Worker CPU/RAMYESOnly if worker resource is bottleneck.
Provider 429 / DB saturationCRITICALMay mean scale DOWN concurrency, not up.
Autoscaling is an optimization, not an MVP requirement. First get correctness, idempotency and visibility right.
23. QUEUES VS SCHEDULER VS BROKER

WORK UNIT, TIME SIGNAL И TRANSPORT — ТРИ РАЗНЫХ ВЕЩИ

№57 QUEUE / WORKER

Who executes backlog?

Persistent executable jobs, claim/lease/ack, concurrency, retry/dead state.

№58 SCHEDULER

When to emit?

At 09:00, every hour, after delay, at deadline — creates signal/job at time boundary.

№59 BROKER

How messages move?

Topics/pub-sub/routing/consumer groups/transport semantics between producers and consumers.

Один продукт может технически реализовать все три роли, но архитектурные responsibilities всё равно стоит различать.
24. QUEUES VS DURABLE WORKFLOW

JOB BACKLOG НЕ РАВЕН ИСТОРИИ ПРОЦЕССА

QUEUE

Execute one work unit

«Parse document 42», «embed chunk batch 7», «send approved message». Worker owns one activity attempt.

№68 DURABLE WORKFLOW

Coordinate long process

«Ingest source → wait → fan-out parsing → aggregate → approval → publish» с history/replay/timers/checkpoints.

Durable workflow engine часто использует queues/workers underneath. Но добавление queue не даёт вам автоматически workflow replay semantics.
25. TESTING & FAILURE INJECTION

WORKER НУЖНО УБИВАТЬ В ТЕСТАХ

DUP

Duplicate delivery

Same job delivered twice → one logical effect.

CRASH

After claim

Worker dies; lease expires; job recovered.

CRASH AFTER EFFECT

Before ACK

Retry does not duplicate external effect.

TIMEOUT

Long job

Timeout leads to clear failure/retry state, no orphan process.

POISON

Always fails

Ends DEAD after policy-defined attempts.

BURST

Load spike

Queue absorbs burst without uncontrolled downstream overload.

DRAIN

Deploy

Graceful shutdown doesn't lose acknowledged work.

TENANT

Isolation

Wrong tenant/priority/resource cannot be injected through job payload.

26. FAILURE MODES

КАК QUEUES & WORKERS ЛОМАЮТСЯ

ACK BEFORE DURABILITY
Job marked success before result/effect is safely persisted.
ACK LAST
NO LEASE EXPIRY
Crashed worker leaves jobs stuck RUNNING forever.
LEASE / VISIBILITY
ASSUME NO DUPLICATES
Retry creates duplicate publish/payment/index rows.
IDEMPOTENT EFFECT
RETRY EVERYTHING
Invalid input/security deny loops forever.
TYPED ERROR CLASSES
NO DEAD STATE
Poison job consumes capacity indefinitely.
MAX ATTEMPTS + DLQ
GIANT PAYLOADS
Queue becomes blob store and retries copy huge data.
ARTIFACT REFS
UNBOUNDED CONCURRENCY
Workers overload DB/provider/GPU during backlog.
CONCURRENCY CAPS
DEPTH-ONLY SCALING
System adds workers despite downstream 429/saturation.
BOTTLENECK-AWARE
QUEUE = WORKFLOW ENGINE
Complex multi-step state encoded as ad-hoc chained jobs.
№68 WHEN NEEDED
27. METRICS

ЧТО ИЗМЕРЯТЬ

AGE

Oldest Job Age

Главный backlog/SLA signal by queue/job type.

Q95

Queue Wait

enqueue → worker start p50/p95.

THR

Throughput

Completed jobs/sec or min, by type/pool.

ARR

Arrival Rate

Created jobs rate vs completion rate.

RTR

Retry Rate

Attempts/job and retry causes.

DLQ

Dead Jobs

Dead count, oldest age, unresolved ownership.

LEX

Lease Expiry

Expired leases / worker loss frequency.

DUP

Duplicate Effect

Logical side effects duplicated after retry. Target: zero.

28. MVP IMPLEMENTATION

POSTGRESQL МОЖЕТ БЫТЬ ВАШЕЙ ПЕРВОЙ QUEUE

jobs(
  job_id            uuid primary key,
  job_type          text,
  tenant_id         text,
  payload_json      jsonb,
  status            text,
  priority          int,
  idempotency_key   text,
  attempt           int,
  max_attempts      int,
  not_before        timestamptz,
  lease_owner       text,
  lease_until       timestamptz,
  created_at        timestamptz,
  started_at        timestamptz,
  finished_at       timestamptz,
  result_ref        text,
  error_json        jsonb
)

claim:
  SELECT ...
  WHERE status='READY'
    AND not_before <= now()
  ORDER BY priority DESC, created_at
  FOR UPDATE SKIP LOCKED
  LIMIT 1

then:
  set LEASED + lease_owner + lease_until
80% VALUE MVP

No dedicated broker required

  • PostgreSQL jobs table.
  • Atomic claim with row locking / SKIP LOCKED.
  • Lease_until + worker heartbeat for long jobs.
  • Typed job contracts.
  • Idempotency key/effect table.
  • Bounded exponential retry.
  • DEAD state + manual redrive.
  • Per-type concurrency.
  • Graceful worker drain.
  • Queue age/depth/retry/dead metrics.

Переходить на dedicated queue/broker, когда throughput, latency, routing, isolation или operational requirements реально выходят за возможности DB-based approach.

29. WHEN TO UPGRADE INFRASTRUCTURE

НЕ МИГРИРОВАТЬ ИЗ POSTGRES «ПОТОМУ ЧТО ТАК ПРАВИЛЬНЕЕ»

SignalPotential next step
Very high job throughput / DB contentionDedicated task queue/broker or partitioned queue architecture.
Complex routing / many independent consumersMessage broker / topics — see №59.
Strict delayed/timed delivery at scaleDedicated scheduler/timer infrastructure — see №58.
Complex multi-day multi-step workflowsDurable workflow engine — see №68.
GPU/heterogeneous poolsQueue routing per capability/resource class.
Multi-region failover / consistency requirementsDistributed reliability design — see №69.
30. PRACTICAL DECISION

СТОИТ ЛИ ДЕЛАТЬ ОТДЕЛЬНЫЙ КОМПОНЕНТ?

ВопросОтвет
Стоит ли реализовывать?Да, когда появляются durable/background/long-running jobs. Для простого synchronous prototype — необязательно.
Separate Component?YES. Queue/worker execution — отдельная production responsibility, хотя MVP может быть таблицей PostgreSQL и worker process.
Минимум 80% ценности?Job contract, durable READY state, atomic claim/lease, idempotent handler, bounded retries, dead state, concurrency caps, metrics.
Когда overkill?Kafka/RabbitMQ/Kubernetes worker fleet для пары фоновых jobs в час, которые надёжно выполняются через Postgres.
Trigger?Work must survive request/process restart, absorb bursts, run later, retry independently or use separate resource pool.
Как измерить uplift?Request latency reduction, completion reliability, oldest age/SLA, throughput, retry/dead rate, duplicate-effect rate, operational incidents.
Можно ли rule/tool/code вместо LLM-agent?Полностью. Queue and worker lifecycle are deterministic infrastructure. LLM may run inside a worker job, but does not implement the queue.
31. DESIGN RULES

ПРАВИЛА ДЛЯ РЕАЛЬНОЙ СИСТЕМЫ

RULE 01

Queue work, not blobs

Передавать small job envelope + references.

RULE 02

Assume redelivery

At-least-once → handlers/effects idempotent.

RULE 03

Lease work

Claim имеет expiry, чтобы crash не блокировал job навсегда.

RULE 04

ACK after durability

Success фиксируется последним, после required effects.

RULE 05

Retry by class

Permanent/security failures не должны бесконечно redrive.

RULE 06

Bound concurrency

Protect downstream providers, DB, GPU and tenants.

RULE 07

Observe age, not only depth

Oldest work and flow rates expose real backlog pressure.

RULE 08

Separate time and transport

Scheduler №58 and Broker №59 are different responsibilities.

RULE 09

Start boring

PostgreSQL queue is valid architecture until requirements prove otherwise.

32. FINAL MAP

CREATE WORK → BUFFER IT → CLAIM IT → FINISH IT SAFELY

USER / EVENT / SYNC / WORKFLOW
        ↓
CREATE WORK UNIT
        ↓
VALIDATE JOB CONTRACT
        ↓
ENQUEUE
  job_id
  type
  tenant
  priority
  idempotency_key
  payload_refs
        ↓
READY BACKLOG
        ↓
WORKER POOL
  capability
  resource class
  concurrency cap
        ↓
ATOMIC CLAIM / LEASE
        ↓
EXECUTE ATTEMPT
        ↓
        ├─ SUCCESS
        │    ↓
        │  persist result/effect
        │    ↓
        │  ACK → SUCCEEDED
        │
        ├─ RETRYABLE
        │    ↓
        │  attempt++
        │  backoff / not_before
        │    ↓
        │  READY
        │
        ├─ PERMANENT
        │    ↓
        │  DEAD
        │
        └─ WORKER CRASH
             ↓
           lease expires
             ↓
           READY AGAIN

CONTROL:
  concurrency
  priorities
  tenant fairness
  resource limits
  retry ceilings
  graceful drain

OBSERVE:
  depth
  oldest age
  queue wait
  execution time
  arrival/completion rate
  retries
  lease expiry
  dead jobs

CORE PRINCIPLE:

THE QUEUE DOES NOT
"RUN THE AI".

IT HOLDS DURABLE,
EXPLICIT UNITS OF WORK.

THE WORKER DOES NOT
"OWN THE PROCESS".

IT CLAIMS ONE UNIT,
EXECUTES IT UNDER A CONTRACT,
AND RETURNS A DURABLE RESULT.

ASSUME DUPLICATES.
BOUND CONCURRENCY.
ACK LAST.
START SIMPLE.

ECC RETROFIT / PRACTICAL HARNESS INTEGRATION

A. Related ECC ideas. Context-as-cache, scoped memory, lifecycle hooks, selective capabilities, feature flags, deterministic enforcement, provider-neutral adapters and eval-gated learning are applied only where relevant to №57 Queues & Workers.

B–E. Existing boundary and placement. The existing conceptual boundary, class PRODUCTION, default CONDITIONAL and owner Production Fabric remain authoritative. Runtime/control/data/offline placement is unchanged; durable state stays outside model context.

F–H. Hooks and contracts. Use bounded PRE_MODEL/POST_MODEL, PRE_TOOL/POST_TOOL, CHECKPOINT and TASK_COMPLETED events as applicable. Illustrative fields and canonical contracts are defined in NEW_CONTRACTS_SPEC.md; no universal schema is implied.

I–J. Security and evaluation. Host-side schema, permission, secret, budget, idempotency and audit checks take precedence over LLM output. Optional mechanisms require a feature flag and WITH/WITHOUT ablation; measure quality, acceptance, correction, latency, cost, escalations and severe errors.

K–L. Task profiles and cross-references. A TaskProfile selects the relevant skill, tool/context slice, memory scope and enforcement profile independently from FAST/STANDARD/DEEP. See cross-reference map, hook spec and ablation plan. Provider adapters remain outside the core.