[{"data":1,"prerenderedAt":402},["ShallowReactive",2],{"navigation":3,"\u002Foperations\u002Fqueue-boundaries":155,"\u002Foperations\u002Fqueue-boundaries-surround":397},[4,36,57,113,144],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":35},"Getting Started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20,25,30],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-info",{"title":16,"path":17,"stem":18,"icon":19},"Install","\u002Fgetting-started\u002Finstall","1.getting-started\u002F2.install","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quickstart","\u002Fgetting-started\u002Fquickstart","1.getting-started\u002F3.quickstart","i-lucide-zap",{"title":26,"path":27,"stem":28,"icon":29},"Testing","\u002Fgetting-started\u002Ftesting","1.getting-started\u002F4.testing","i-lucide-flask-conical",{"title":31,"path":32,"stem":33,"icon":34},"CLI","\u002Fgetting-started\u002Fcli","1.getting-started\u002F5.cli","i-lucide-terminal",false,{"title":37,"icon":38,"path":39,"stem":40,"children":41,"page":35},"Concepts","i-lucide-boxes","\u002Fconcepts","2.concepts",[42,47,52],{"title":43,"path":44,"stem":45,"icon":46},"SQL-first contract","\u002Fconcepts\u002Fsql-first-contract","2.concepts\u002F1.sql-first-contract","i-lucide-database",{"title":48,"path":49,"stem":50,"icon":51},"Jobs and status","\u002Fconcepts\u002Fjobs-and-status","2.concepts\u002F2.jobs-and-status","i-lucide-list-checks",{"title":53,"path":54,"stem":55,"icon":56},"Fencing and settles","\u002Fconcepts\u002Ffencing-and-settles","2.concepts\u002F3.fencing-and-settles","i-lucide-shield",{"title":58,"icon":59,"path":60,"stem":61,"children":62,"page":35},"API","i-lucide-code-2","\u002Fapi","3.api",[63,68,73,78,83,88,93,98,103,108],{"title":64,"path":65,"stem":66,"icon":67},"Enqueue","\u002Fapi\u002Fenqueue","3.api\u002F1.enqueue","i-lucide-plus-circle",{"title":69,"path":70,"stem":71,"icon":72},"Trusted Effects","\u002Fapi\u002Ftrusted-effects","3.api\u002F10.trusted-effects","i-lucide-lock-keyhole",{"title":74,"path":75,"stem":76,"icon":77},"Claim and heartbeat","\u002Fapi\u002Fclaim-and-heartbeat","3.api\u002F2.claim-and-heartbeat","i-lucide-hand",{"title":79,"path":80,"stem":81,"icon":82},"Worker and handlers","\u002Fapi\u002Fworker-and-handlers","3.api\u002F3.worker-and-handlers","i-lucide-cpu",{"title":84,"path":85,"stem":86,"icon":87},"HTTP facade","\u002Fapi\u002Fhttp-facade","3.api\u002F4.http-facade","i-lucide-globe",{"title":89,"path":90,"stem":91,"icon":92},"Authorization","\u002Fapi\u002Fauthorization","3.api\u002F5.authorization","i-lucide-key-round",{"title":94,"path":95,"stem":96,"icon":97},"Follow-ups","\u002Fapi\u002Ffollow-ups","3.api\u002F6.follow-ups","i-lucide-git-branch",{"title":99,"path":100,"stem":101,"icon":102},"Workflows and schedules","\u002Fapi\u002Fworkflows-and-schedules","3.api\u002F7.workflows-and-schedules","i-lucide-workflow",{"title":104,"path":105,"stem":106,"icon":107},"Durable admission","\u002Fapi\u002Fdurable-admission","3.api\u002F8.durable-admission","i-lucide-ticket",{"title":109,"path":110,"stem":111,"icon":112},"Workflow Continuations","\u002Fapi\u002Fworkflow-continuations","3.api\u002F9.workflow-continuations","i-lucide-git-fork",{"title":114,"icon":115,"path":116,"stem":117,"children":118,"page":35},"Operations","i-lucide-activity","\u002Foperations","4.operations",[119,124,129,134,139],{"title":120,"path":121,"stem":122,"icon":123},"Standalone Scheduler","\u002Foperations\u002Fstandalone-scheduler","4.operations\u002F0.standalone-scheduler","i-lucide-calendar-clock",{"title":125,"path":126,"stem":127,"icon":128},"Housekeeping","\u002Foperations\u002Fhousekeeping","4.operations\u002F1.housekeeping","i-lucide-timer",{"title":130,"path":131,"stem":132,"icon":133},"Redrive and dead letters","\u002Foperations\u002Fredrive-and-dlq","4.operations\u002F2.redrive-and-dlq","i-lucide-rotate-ccw",{"title":135,"path":136,"stem":137,"icon":138},"Flow control","\u002Foperations\u002Fflow-control","4.operations\u002F3.flow-control","i-lucide-gauge",{"title":140,"path":141,"stem":142,"icon":143},"Queue Boundaries","\u002Foperations\u002Fqueue-boundaries","4.operations\u002F4.queue-boundaries","i-lucide-panels-top-left",{"title":145,"icon":146,"path":147,"stem":148,"children":149,"page":35},"Reference","i-lucide-book-marked","\u002Freference","5.reference",[150],{"title":151,"path":152,"stem":153,"icon":154},"Configuration","\u002Freference\u002Fconfiguration","5.reference\u002F1.configuration","i-lucide-settings",{"id":156,"title":140,"body":157,"description":390,"extension":391,"links":392,"meta":393,"navigation":394,"path":141,"seo":395,"stem":142,"__hash__":396},"docs\u002F4.operations\u002F4.queue-boundaries.md",{"type":158,"value":159,"toc":379},"minimark",[160,169,172,177,180,199,202,208,212,215,218,278,282,285,288,311,315,318,321,324,328,331,351,354,358],[161,162,163,164,168],"p",{},"A TaskQ queue is an ",[165,166,167],"strong",{},"operational control boundary",". It is not a database-table\nboundary and it is not just a label for a task type.",[161,170,171],{},"Jobs in separate queues may safely use the same application tables when the\napplication enforces transactions, fencing, idempotency, and domain invariants.\nThe queue isolates the controls around that work: pause\u002Fresume, drain, depth,\nflow limits, circuit breakers, worker ownership, credentials, and recovery.",[173,174,176],"h2",{"id":175},"one-owner-decision-test","One-owner decision test",[161,178,179],{},"Put workloads in the same queue only when one operational owner can safely make\nthe same decision for every job in it:",[181,182,183,187,190,193,196],"ul",{},[184,185,186],"li",{},"pause, resume, drain, purge, and redrive;",[184,188,189],{},"worker placement, concurrency, and rollout timing;",[184,191,192],{},"depth, claim rate, circuit breaker, and recovery ramp;",[184,194,195],{},"credentials, downstream quotas, and provider spend;",[184,197,198],{},"failure classification, recovery procedure, and service objective.",[161,200,201],{},"If two workloads need independent answers to any item, use separate queues.\nA controller that pauses or drains a queue controls every task type in that\nqueue; task-type filtering does not make a queue-wide action safe.",[203,204,205],"caution",{},[161,206,207],{},"Do not place unrelated campaign controllers in one queue merely because their\nhandlers update the same tables. That couples their pause\u002Fdrain lifecycle and\ncan make one campaign stop another.",[173,209,211],{"id":210},"share-related-stages-deliberately","Share related stages deliberately",[161,213,214],{},"Related stages may share one queue when they intentionally have the same owner,\ncapacity budget, availability target, and recovery lifecycle. A render pipeline\ncan share a render queue when a render-wide pause is supposed to stop prepare,\nexecute, verify, and upload together.",[161,216,217],{},"Do not create one queue per job, handler, workflow step, process, or container.\nUse:",[219,220,221,234],"table",{},[222,223,224],"thead",{},[225,226,227,231],"tr",{},[228,229,230],"th",{},"Need",[228,232,233],{},"TaskQ mechanism",[235,236,237,246,254,262,270],"tbody",{},[225,238,239,243],{},[240,241,242],"td",{},"Dispatch different payloads",[240,244,245],{},"Task types and registries",[225,247,248,251],{},[240,249,250],{},"Express stage dependencies",[240,252,253],{},"Workflows and follow-ups",[225,255,256,259],{},[240,257,258],{},"Place work on a lane",[240,260,261],{},"Worker queue\u002Ftask filters",[225,263,264,267],{},[240,265,266],{},"Limit a real shared resource",[240,268,269],{},"Concurrency or flow keys",[225,271,272,275],{},[240,273,274],{},"Control a workload independently",[240,276,277],{},"A separate queue",[173,279,281],{"id":280},"isolation-does-not-create-capacity","Isolation does not create capacity",[161,283,284],{},"Separate queues protect control and admission. They still share the TaskQ\ninstallation's Postgres CPU, storage I\u002FO, API capacity, network, and any common\nprovider quotas.",[161,286,287],{},"For concurrent queues:",[289,290,291,299,302,305,308],"ol",{},[184,292,293,294,298],{},"set an explicit per-queue ",[295,296,297],"code",{},"max_running",", claim rate, and depth;",[184,300,301],{},"bound worker concurrency and credential request budgets;",[184,303,304],{},"measure planning\u002Fenqueue cost as well as handler cost;",[184,306,307],{},"load-test cross-queue latency under shared database saturation;",[184,309,310],{},"use another TaskQ installation only when physical resource or failure-domain\nisolation is required.",[173,312,314],{"id":313},"safe-bootstrap-and-deployment","Safe bootstrap and deployment",[161,316,317],{},"Queue catalog reconciliation must preserve every existing queue's open or\npaused state. A newly created queue can start paused for its canary; bootstrap\nmust not pause or resume unrelated queues as a side effect.",[161,319,320],{},"Treat queue names as stable operational API. Give producers, workers, and\ncontrollers least-privilege access to their queues. Run one supervised\nscheduler clock per TaskQ installation; the scheduler does not own every queue.",[161,322,323],{},"Durable workers require an always-on host and an external service supervisor\nwith restart policy and observable health. Laptop batteries, lid state,\nsleep-prevention tools, and interactive login sessions are not production\navailability controls. Use a laptop only for attended, bounded work whose\ninterruption and lease recovery are understood.",[173,325,327],{"id":326},"prove-the-boundary","Prove the boundary",[161,329,330],{},"Before opening multiple queues in production, test against the real TaskQ\ndatabase and authorization layer:",[181,332,333,336,339,342,345,348],{},[184,334,335],{},"pause\u002Fdrain queue A while queue B stays open and settles work;",[184,337,338],{},"reconcile the catalog without changing any existing queue state;",[184,340,341],{},"deny every producer, worker, and controller on queues it does not own;",[184,343,344],{},"run both queues together and verify independent presence, counters, depth,\nlimits, and breakers;",[184,346,347],{},"terminate a worker and prove supervised restart or lease-expiry recovery\nwithout duplicate external effects;",[184,349,350],{},"saturate shared capacity and verify backpressure without control coupling.",[161,352,353],{},"Keep the queue-to-workload ownership map beside the worker registry and\ndeployment manifest. Review it whenever a new controller, provider, worker\nfamily, or service objective is introduced.",[173,355,357],{"id":356},"related","Related",[181,359,360,366,370,374],{},[184,361,362],{},[363,364,365],"a",{"href":136},"Flow Control",[184,367,368],{},[363,369,120],{"href":121},[184,371,372],{},[363,373,89],{"href":90},[184,375,376],{},[363,377,378],{"href":80},"Workers & Handlers",{"title":380,"searchDepth":381,"depth":382,"links":383},"",1,2,[384,385,386,387,388,389],{"id":175,"depth":382,"text":176},{"id":210,"depth":382,"text":211},{"id":280,"depth":382,"text":281},{"id":313,"depth":382,"text":314},{"id":326,"depth":382,"text":327},{"id":356,"depth":382,"text":357},"Design queues as independent operational bulkheads without confusing them with database or task-type boundaries.","md",null,{},{"icon":143},{"title":140,"description":390},"dwyXcTtUCRrkdFzSDsNDhD5qy8YuK6CcrSNH-3WQAgQ",[398,400],{"title":135,"path":136,"stem":137,"description":399,"icon":138,"children":-1},"Circuit breaker, rate limits, in-flight caps, slow-start ramps, TTL, smear, and priority aging — everything off by default, per queue.",{"title":151,"path":152,"stem":153,"description":401,"icon":154,"children":-1},"Queue profiles and WorkerSettings \u002F TASKQ_* knobs.",1787515777647]