[{"data":1,"prerenderedAt":2064},["ShallowReactive",2],{"navigation_docs":3,"-docs-capabilities-background-jobs":493,"-docs-capabilities-background-jobs-surround":2059},[4,46,135,218,257,292,355,377,420],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":45},"Getting Started","i-lucide-rocket","\u002Fdocs\u002Fgetting-started","docs\u002F01.getting-started",[10,15,20,25,30,35,40],{"title":11,"path":12,"stem":13,"icon":14},"What is Heximon?","\u002Fdocs\u002Fgetting-started\u002Fintroduction","docs\u002F01.getting-started\u002F01.introduction","i-lucide-info",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fdocs\u002Fgetting-started\u002Finstallation","docs\u002F01.getting-started\u002F02.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick Start","\u002Fdocs\u002Fgetting-started\u002Fquick-start","docs\u002F01.getting-started\u002F03.quick-start","i-lucide-zap",{"title":26,"path":27,"stem":28,"icon":29},"Core Concepts","\u002Fdocs\u002Fgetting-started\u002Fcore-concepts","docs\u002F01.getting-started\u002F04.core-concepts","i-lucide-shapes",{"title":31,"path":32,"stem":33,"icon":34},"Examples","\u002Fdocs\u002Fgetting-started\u002Fexamples","docs\u002F01.getting-started\u002F05.examples","i-lucide-library",{"title":36,"path":37,"stem":38,"icon":39},"Where Next?","\u002Fdocs\u002Fgetting-started\u002Fwhere-next","docs\u002F01.getting-started\u002F06.where-next","i-lucide-signpost",{"title":41,"path":42,"stem":43,"icon":44},"Troubleshooting","\u002Fdocs\u002Fgetting-started\u002Ftroubleshooting","docs\u002F01.getting-started\u002F07.troubleshooting","i-lucide-life-buoy",false,{"title":47,"icon":48,"path":49,"stem":50,"children":51,"page":45},"Essentials","i-lucide-boxes","\u002Fdocs\u002Fessentials","docs\u002F02.essentials",[52,56,61,66,71,76,81,86,91,96,101,105,110,115,120,125,130],{"title":53,"path":54,"stem":55,"icon":48},"Modules & DI","\u002Fdocs\u002Fessentials\u002Fmodules-and-di","docs\u002F02.essentials\u002F01.modules-and-di",{"title":57,"path":58,"stem":59,"icon":60},"Controllers","\u002Fdocs\u002Fessentials\u002Fcontrollers","docs\u002F02.essentials\u002F02.controllers","i-lucide-route",{"title":62,"path":63,"stem":64,"icon":65},"Validation & DTOs","\u002Fdocs\u002Fessentials\u002Fvalidation","docs\u002F02.essentials\u002F03.validation","i-lucide-shield-check",{"title":67,"path":68,"stem":69,"icon":70},"Contracts","\u002Fdocs\u002Fessentials\u002Fcontracts","docs\u002F02.essentials\u002F04.contracts","i-lucide-file-signature",{"title":72,"path":73,"stem":74,"icon":75},"REST Client","\u002Fdocs\u002Fessentials\u002Fclient","docs\u002F02.essentials\u002F05.client","i-lucide-plug",{"title":77,"path":78,"stem":79,"icon":80},"Database","\u002Fdocs\u002Fessentials\u002Fdatabase","docs\u002F02.essentials\u002F06.database","i-lucide-database",{"title":82,"path":83,"stem":84,"icon":85},"Drizzle ORM","\u002Fdocs\u002Fessentials\u002Fdrizzle","docs\u002F02.essentials\u002F07.drizzle","i-lucide-database-zap",{"title":87,"path":88,"stem":89,"icon":90},"Persistence & Transactions","\u002Fdocs\u002Fessentials\u002Fpersistence","docs\u002F02.essentials\u002F08.persistence","i-lucide-database-backup",{"title":92,"path":93,"stem":94,"icon":95},"Migrations","\u002Fdocs\u002Fessentials\u002Fmigrations","docs\u002F02.essentials\u002F09.migrations","i-lucide-git-branch",{"title":97,"path":98,"stem":99,"icon":100},"Authentication","\u002Fdocs\u002Fessentials\u002Fauthentication","docs\u002F02.essentials\u002F10.authentication","i-lucide-key-round",{"title":102,"path":103,"stem":104,"icon":65},"Permissions & scopes","\u002Fdocs\u002Fessentials\u002Fpermissions","docs\u002F02.essentials\u002F11.permissions",{"title":106,"path":107,"stem":108,"icon":109},"Error Handling","\u002Fdocs\u002Fessentials\u002Ferrors","docs\u002F02.essentials\u002F12.errors","i-lucide-triangle-alert",{"title":111,"path":112,"stem":113,"icon":114},"Testing a Heximon App","\u002Fdocs\u002Fessentials\u002Ftesting","docs\u002F02.essentials\u002F13.testing","i-lucide-flask-conical",{"title":116,"path":117,"stem":118,"icon":119},"Test app harness","\u002Fdocs\u002Fessentials\u002Fcreatetestapp","docs\u002F02.essentials\u002F14.createtestapp","i-lucide-test-tube",{"title":121,"path":122,"stem":123,"icon":124},"Logging & Observability","\u002Fdocs\u002Fessentials\u002Flogging","docs\u002F02.essentials\u002F17.logging","i-lucide-scroll-text",{"title":126,"path":127,"stem":128,"icon":129},"Context & Lifecycle","\u002Fdocs\u002Fessentials\u002Fcontext-and-lifecycle","docs\u002F02.essentials\u002F18.context-and-lifecycle","i-lucide-radio",{"title":131,"path":132,"stem":133,"icon":134},"Project Structure","\u002Fdocs\u002Fessentials\u002Fproject-structure","docs\u002F02.essentials\u002F19.project-structure","i-lucide-folder-tree",{"title":136,"icon":137,"path":138,"stem":139,"children":140,"page":45},"Capabilities","i-lucide-sparkles","\u002Fdocs\u002Fcapabilities","docs\u002F03.capabilities",[141,145,150,155,160,164,169,174,179,184,188,193,198,203,208,213],{"title":142,"path":143,"stem":144,"icon":137},"Overview","\u002Fdocs\u002Fcapabilities\u002Foverview","docs\u002F03.capabilities\u002F01.overview",{"title":146,"path":147,"stem":148,"icon":149},"Events","\u002Fdocs\u002Fcapabilities\u002Fevents","docs\u002F03.capabilities\u002F02.events","i-lucide-radio-tower",{"title":151,"path":152,"stem":153,"icon":154},"Queue","\u002Fdocs\u002Fcapabilities\u002Fbackground-jobs","docs\u002F03.capabilities\u002F03.background-jobs","i-lucide-list-ordered",{"title":156,"path":157,"stem":158,"icon":159},"Scheduled Work","\u002Fdocs\u002Fcapabilities\u002Fscheduled-jobs","docs\u002F03.capabilities\u002F04.scheduled-jobs","i-lucide-clock",{"title":161,"path":162,"stem":163,"icon":85},"Caching","\u002Fdocs\u002Fcapabilities\u002Fcaching","docs\u002F03.capabilities\u002F05.caching",{"title":165,"path":166,"stem":167,"icon":168},"Key\u002FValue Storage","\u002Fdocs\u002Fcapabilities\u002Fkey-value","docs\u002F03.capabilities\u002F06.key-value","i-lucide-hard-drive",{"title":170,"path":171,"stem":172,"icon":173},"Blob Storage","\u002Fdocs\u002Fcapabilities\u002Fblob","docs\u002F03.capabilities\u002F07.blob","i-lucide-folder-open",{"title":175,"path":176,"stem":177,"icon":178},"Health & Readiness","\u002Fdocs\u002Fcapabilities\u002Fhealth","docs\u002F03.capabilities\u002F08.health","i-lucide-heart-pulse",{"title":180,"path":181,"stem":182,"icon":183},"Notifications","\u002Fdocs\u002Fcapabilities\u002Fnotifications","docs\u002F03.capabilities\u002F09.notifications","i-lucide-mail",{"title":185,"path":186,"stem":187,"icon":65},"Idempotency","\u002Fdocs\u002Fcapabilities\u002Fidempotency","docs\u002F03.capabilities\u002F10.idempotency",{"title":189,"path":190,"stem":191,"icon":192},"Security Hardening","\u002Fdocs\u002Fcapabilities\u002Fsecurity","docs\u002F03.capabilities\u002F11.security","i-lucide-shield",{"title":194,"path":195,"stem":196,"icon":197},"Observability & Tracing","\u002Fdocs\u002Fcapabilities\u002Fobservability","docs\u002F03.capabilities\u002F12.observability","i-lucide-activity",{"title":199,"path":200,"stem":201,"icon":202},"OpenAPI","\u002Fdocs\u002Fcapabilities\u002Fopenapi","docs\u002F03.capabilities\u002F13.openapi","i-lucide-book-marked",{"title":204,"path":205,"stem":206,"icon":207},"MCP Server","\u002Fdocs\u002Fcapabilities\u002Fmcp","docs\u002F03.capabilities\u002F14.mcp","i-lucide-bot",{"title":209,"path":210,"stem":211,"icon":212},"Schema DTOs","\u002Fdocs\u002Fcapabilities\u002Fschema","docs\u002F03.capabilities\u002F15.schema","i-lucide-file-json",{"title":214,"path":215,"stem":216,"icon":217},"Branded IDs","\u002Fdocs\u002Fcapabilities\u002Fbranded-ids","docs\u002F03.capabilities\u002F16.branded-ids","i-lucide-tag",{"title":219,"icon":220,"path":221,"stem":222,"children":223,"page":45},"Architecture","i-lucide-building","\u002Fdocs\u002Farchitecture","docs\u002F04.architecture",[224,227,232,237,242,247,252],{"title":142,"path":225,"stem":226,"icon":220},"\u002Fdocs\u002Farchitecture\u002Foverview","docs\u002F04.architecture\u002F01.overview",{"title":228,"path":229,"stem":230,"icon":231},"Domain-Driven Design","\u002Fdocs\u002Farchitecture\u002Fddd","docs\u002F04.architecture\u002F02.ddd","i-lucide-hexagon",{"title":233,"path":234,"stem":235,"icon":236},"CQRS","\u002Fdocs\u002Farchitecture\u002Fcqrs","docs\u002F04.architecture\u002F03.cqrs","i-lucide-split",{"title":238,"path":239,"stem":240,"icon":241},"Repository Pattern","\u002Fdocs\u002Farchitecture\u002Frepository-pattern","docs\u002F04.architecture\u002F04.repository-pattern","i-lucide-archive",{"title":243,"path":244,"stem":245,"icon":246},"Integration Events","\u002Fdocs\u002Farchitecture\u002Fintegration-events","docs\u002F04.architecture\u002F05.integration-events","i-lucide-send-horizontal",{"title":248,"path":249,"stem":250,"icon":251},"Saga Orchestration","\u002Fdocs\u002Farchitecture\u002Fsagas","docs\u002F04.architecture\u002F06.sagas","i-lucide-hourglass",{"title":253,"path":254,"stem":255,"icon":256},"Durable Workflows","\u002Fdocs\u002Farchitecture\u002Fworkflows","docs\u002F04.architecture\u002F07.workflows","i-lucide-workflow",{"title":258,"icon":259,"path":260,"stem":261,"children":262,"page":45},"Realtime","i-lucide-cable","\u002Fdocs\u002Frealtime","docs\u002F05.realtime",[263,266,270,274,279,284,288],{"title":142,"path":264,"stem":265,"icon":259},"\u002Fdocs\u002Frealtime\u002Foverview","docs\u002F05.realtime\u002F01.overview",{"title":267,"path":268,"stem":269,"icon":129},"WebSockets","\u002Fdocs\u002Frealtime\u002Fwebsockets","docs\u002F05.realtime\u002F02.websockets",{"title":271,"path":272,"stem":273,"icon":70},"WebSocket Contracts","\u002Fdocs\u002Frealtime\u002Fwebsocket-contracts","docs\u002F05.realtime\u002F03.websocket-contracts",{"title":275,"path":276,"stem":277,"icon":278},"Server-Sent Events","\u002Fdocs\u002Frealtime\u002Fserver-sent-events","docs\u002F05.realtime\u002F04.server-sent-events","i-lucide-rss",{"title":280,"path":281,"stem":282,"icon":283},"Typed Clients","\u002Fdocs\u002Frealtime\u002Ftyped-clients","docs\u002F05.realtime\u002F05.typed-clients","i-lucide-plug-zap",{"title":285,"path":286,"stem":287,"icon":259},"AsyncAPI","\u002Fdocs\u002Frealtime\u002Fasyncapi","docs\u002F05.realtime\u002F06.asyncapi",{"title":289,"path":290,"stem":291,"icon":80},"Durable Objects","\u002Fdocs\u002Frealtime\u002Fdurable-objects","docs\u002F05.realtime\u002F07.durable-objects",{"title":293,"icon":294,"path":295,"stem":296,"children":297,"page":45},"Deploy","i-lucide-cloud-upload","\u002Fdocs\u002Fdeploy","docs\u002F06.deploy",[298,301,306,311,316,321,326,331,336,341,345,350],{"title":142,"path":299,"stem":300,"icon":6},"\u002Fdocs\u002Fdeploy\u002Foverview","docs\u002F06.deploy\u002F01.overview",{"title":302,"path":303,"stem":304,"icon":305},"Node","\u002Fdocs\u002Fdeploy\u002Fnode","docs\u002F06.deploy\u002F02.node","la:node-js",{"title":307,"path":308,"stem":309,"icon":310},"Cloudflare","\u002Fdocs\u002Fdeploy\u002Fcloudflare","docs\u002F06.deploy\u002F03.cloudflare","simple-icons:cloudflare",{"title":312,"path":313,"stem":314,"icon":315},"Vercel","\u002Fdocs\u002Fdeploy\u002Fvercel","docs\u002F06.deploy\u002F04.vercel","ri:vercel-fill",{"title":317,"path":318,"stem":319,"icon":320},"Netlify","\u002Fdocs\u002Fdeploy\u002Fnetlify","docs\u002F06.deploy\u002F05.netlify","i-simple-icons-netlify",{"title":322,"path":323,"stem":324,"icon":325},"AWS Lambda","\u002Fdocs\u002Fdeploy\u002Faws-lambda","docs\u002F06.deploy\u002F06.aws-lambda","hugeicons:aws-lambda",{"title":327,"path":328,"stem":329,"icon":330},"Deno Deploy","\u002Fdocs\u002Fdeploy\u002Fdeno-deploy","docs\u002F06.deploy\u002F07.deno-deploy","simple-icons:denodeploy",{"title":332,"path":333,"stem":334,"icon":335},"Nitro","\u002Fdocs\u002Fdeploy\u002Fnitro","docs\u002F06.deploy\u002F08.nitro","i-unjs-nitro",{"title":337,"path":338,"stem":339,"icon":340},"Nuxt","\u002Fdocs\u002Fdeploy\u002Fnuxt","docs\u002F06.deploy\u002F09.nuxt","i-devicon-nuxt",{"title":342,"path":343,"stem":344,"icon":236},"Mixed-runtime split","\u002Fdocs\u002Fdeploy\u002Fmixed-runtime-split","docs\u002F06.deploy\u002F10.mixed-runtime-split",{"title":346,"path":347,"stem":348,"icon":349},"Hosts","\u002Fdocs\u002Fdeploy\u002Fhosts","docs\u002F06.deploy\u002F11.hosts","i-lucide-map",{"title":351,"path":352,"stem":353,"icon":354},"Cross-service events","\u002Fdocs\u002Fdeploy\u002Fcross-service-events","docs\u002F06.deploy\u002F12.cross-service-events","i-lucide-network",{"title":356,"icon":357,"path":358,"stem":359,"children":360,"page":45},"CLI","i-lucide-terminal","\u002Fdocs\u002Fcli","docs\u002F07.cli",[361,365,369,373],{"title":362,"path":363,"stem":364,"icon":357},"The heximon CLI","\u002Fdocs\u002Fcli\u002Foverview","docs\u002F07.cli\u002F01.overview",{"title":366,"path":367,"stem":368,"icon":137},"Create a New App","\u002Fdocs\u002Fcli\u002Fcreate","docs\u002F07.cli\u002F02.create",{"title":370,"path":371,"stem":372,"icon":95},"Migrations from the CLI","\u002Fdocs\u002Fcli\u002Fmigrations","docs\u002F07.cli\u002F03.migrations",{"title":374,"path":375,"stem":376,"icon":6},"Deploying a Heximon app","\u002Fdocs\u002Fcli\u002Fdeploy","docs\u002F07.cli\u002F04.deploy",{"title":378,"icon":379,"path":380,"stem":381,"children":382,"page":45},"Under the Hood","i-lucide-wrench","\u002Fdocs\u002Funder-the-hood","docs\u002F08.under-the-hood",[383,388,393,397,402,407,411,415],{"title":384,"path":385,"stem":386,"icon":387},"How the Compiler Works","\u002Fdocs\u002Funder-the-hood\u002Fhow-the-compiler-works","docs\u002F08.under-the-hood\u002F01.how-the-compiler-works","i-lucide-cog",{"title":389,"path":390,"stem":391,"icon":392},"Compiler","\u002Fdocs\u002Funder-the-hood\u002Fextending-the-compiler","docs\u002F08.under-the-hood\u002F02.extending-the-compiler","i-lucide-cpu",{"title":394,"path":395,"stem":396,"icon":357},"Compiler Diagnostics","\u002Fdocs\u002Funder-the-hood\u002Fcompiler-diagnostics","docs\u002F08.under-the-hood\u002F03.compiler-diagnostics",{"title":398,"path":399,"stem":400,"icon":401},"Library Mode","\u002Fdocs\u002Funder-the-hood\u002Flibrary-mode","docs\u002F08.under-the-hood\u002F04.library-mode","i-lucide-package",{"title":403,"path":404,"stem":405,"icon":406},"Other bundlers","\u002Fdocs\u002Funder-the-hood\u002Falternate-bundlers","docs\u002F08.under-the-hood\u002F05.alternate-bundlers","i-lucide-blocks",{"title":408,"path":409,"stem":410,"icon":401},"Packages","\u002Fdocs\u002Funder-the-hood\u002Fpackages","docs\u002F08.under-the-hood\u002F06.packages",{"title":412,"path":413,"stem":414,"icon":207},"AI Skills","\u002Fdocs\u002Funder-the-hood\u002Fai-and-agents","docs\u002F08.under-the-hood\u002F07.ai-and-agents",{"title":416,"path":417,"stem":418,"icon":419},"Advanced DI","\u002Fdocs\u002Funder-the-hood\u002Fadvanced-di","docs\u002F08.under-the-hood\u002F08.advanced-di","i-lucide-git-fork",{"title":421,"icon":422,"path":423,"stem":424,"children":425,"page":45},"Recipes","i-lucide-book-open-check","\u002Fdocs\u002Frecipes","docs\u002F09.recipes",[426,431,436,440,444,448,452,456,460,465,469,474,479,484,488],{"title":427,"path":428,"stem":429,"icon":430},"Send an Email","\u002Fdocs\u002Frecipes\u002Fsend-an-email","docs\u002F09.recipes\u002F01.send-an-email","i-lucide-send",{"title":432,"path":433,"stem":434,"icon":435},"Upload a File","\u002Fdocs\u002Frecipes\u002Fupload-a-file","docs\u002F09.recipes\u002F02.upload-a-file","i-lucide-upload",{"title":437,"path":438,"stem":439,"icon":24},"Cache an Expensive Call","\u002Fdocs\u002Frecipes\u002Fcache-an-expensive-call","docs\u002F09.recipes\u002F03.cache-an-expensive-call",{"title":441,"path":442,"stem":443,"icon":154},"Paginate a List","\u002Fdocs\u002Frecipes\u002Fpaginate-a-list","docs\u002F09.recipes\u002F04.paginate-a-list",{"title":445,"path":446,"stem":447,"icon":65},"Protect Admin Routes","\u002Fdocs\u002Frecipes\u002Fprotect-admin-routes","docs\u002F09.recipes\u002F05.protect-admin-routes",{"title":449,"path":450,"stem":451,"icon":178},"Health Probes and a Nightly Job","\u002Fdocs\u002Frecipes\u002Fhealth-probes-and-a-nightly-job","docs\u002F09.recipes\u002F06.health-probes-and-a-nightly-job",{"title":453,"path":454,"stem":455,"icon":80},"Build a CRUD API","\u002Fdocs\u002Frecipes\u002Fcrud-api","docs\u002F09.recipes\u002F07.crud-api",{"title":457,"path":458,"stem":459,"icon":100},"Add Authentication","\u002Fdocs\u002Frecipes\u002Fadd-authentication","docs\u002F09.recipes\u002F08.add-authentication",{"title":461,"path":462,"stem":463,"icon":464},"Background Jobs","\u002Fdocs\u002Frecipes\u002Fbackground-jobs","docs\u002F09.recipes\u002F09.background-jobs","i-lucide-timer",{"title":466,"path":467,"stem":468,"icon":149},"Decouple Features with Events","\u002Fdocs\u002Frecipes\u002Fevent-driven-module","docs\u002F09.recipes\u002F10.event-driven-module",{"title":470,"path":471,"stem":472,"icon":473},"Build a DDD Aggregate","\u002Fdocs\u002Frecipes\u002Fddd-aggregate","docs\u002F09.recipes\u002F11.ddd-aggregate","i-lucide-box",{"title":475,"path":476,"stem":477,"icon":478},"Publish a Feature Package","\u002Fdocs\u002Frecipes\u002Ffeature-package","docs\u002F09.recipes\u002F12.feature-package","i-lucide-package-open",{"title":480,"path":481,"stem":482,"icon":483},"Reliable Integration Events","\u002Fdocs\u002Frecipes\u002Freliable-integration-events","docs\u002F09.recipes\u002F13.reliable-integration-events","i-lucide-inbox",{"title":485,"path":486,"stem":487,"icon":95},"Reactive Choreography","\u002Fdocs\u002Frecipes\u002Freactive-choreography","docs\u002F09.recipes\u002F14.reactive-choreography",{"title":489,"path":490,"stem":491,"icon":492},"Build a Production CRUD API","\u002Fdocs\u002Frecipes\u002Fproduction-crud-api","docs\u002F09.recipes\u002F15.production-crud-api","i-lucide-layers",{"id":494,"title":151,"body":495,"description":2052,"extension":2053,"links":2054,"meta":2055,"navigation":2056,"path":152,"seo":2057,"stem":153,"__hash__":2058},"docs\u002Fdocs\u002F03.capabilities\u002F03.background-jobs.md",{"type":496,"value":497,"toc":2041},"minimark",[498,511,514,519,533,544,551,555,565,734,740,1068,1078,1082,1093,1303,1314,1318,1332,1512,1519,1594,1620,1624,1643,1666,1771,1775,1797,1801,1816,1927,1946,1950,1968,1972,2037],[499,500,501,502,506,507,510],"p",{},"Move slow work off the request path. Your code publishes a message onto a named ",[503,504,505],"strong",{},"channel"," and returns\nright away; a ",[503,508,509],{},"consumer"," picks it up later and runs your handler — with automatic retry and optional\npayload validation. The channel is durable, so the work survives the request that triggered it having\nalready returned.",[499,512,513],{},"The same handler code runs on every backend: an in-process queue while you develop, a durable platform\nqueue in production. You swap the transport, not your handlers.",[515,516,518],"h2",{"id":517},"the-shape","The shape",[499,520,521,522,525,526,529,530,532],{},"A queue is one idea with three moving parts: a ",[503,523,524],{},"producer"," publishes, a ",[503,527,528],{},"transport"," holds the message,\nand a ",[503,531,509],{}," drains it back into your handlers.",[534,535,541],"pre",{"className":536,"code":538,"language":539,"meta":540},[537],"language-text"," your code\n    │\n    │  queue.publish(\"orders-placed\", payload)      returns immediately — fire-and-forget\n    ▼\n ┌──────────────────────────── transport ─────────────────────────────┐\n │  dev \u002F test    MemoryQueue             in-process, drains this tick│\n │  production    a durable queue         one per platform (see table)│\n └────────────────────────────────────────────────────────────────────┘\n    │  delivered later\n    ▼\n consumer  ──►  QueueChannelDispatcher  ──►  every handler bound to the channel\n                                             (each runs with retry + optional validation)\n    ▼\n class OrderPlacedHandler implements QueueEventHandler\u003C\"orders-placed\", OrderPlaced> {\n   handle(payload) { … }\n }\n","text","",[542,543,538],"code",{"__ignoreMap":540},[499,545,546,547,550],{},"Everything below the ",[542,548,549],{},"publish"," line is the framework's job — you write only the producer call, the handler,\nand one line of module config.",[515,552,554],{"id":553},"publish-onto-a-channel","Publish onto a channel",[499,556,557,558,561,562,564],{},"Channels and their payloads live in one typed map. Extending ",[542,559,560],{},"QueueEventTypes"," makes the map the contract\nboth sides share, so ",[542,563,549],{}," rejects an unknown channel or a mismatched payload at compile time.",[534,566,571],{"className":567,"code":568,"filename":569,"language":570,"meta":540,"style":540},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import type { QueueEventTypes } from \"@heximon\u002Fqueue\";\n\nexport interface OrderPlaced {\n  readonly orderId: string;\n  readonly sku: string;\n  readonly quantity: number;\n}\n\nexport interface OrderEventMap extends QueueEventTypes {\n  readonly \"orders-placed\": OrderPlaced;\n}\n","orders\u002Forder-events.ts","ts",[542,572,573,612,619,636,654,668,683,689,694,711,729],{"__ignoreMap":540},[574,575,578,582,585,589,593,596,599,602,606,609],"span",{"class":576,"line":577},"line",1,[574,579,581],{"class":580},"s7zQu","import",[574,583,584],{"class":580}," type",[574,586,588],{"class":587},"sMK4o"," {",[574,590,592],{"class":591},"sTEyZ"," QueueEventTypes",[574,594,595],{"class":587}," }",[574,597,598],{"class":580}," from",[574,600,601],{"class":587}," \"",[574,603,605],{"class":604},"sfazB","@heximon\u002Fqueue",[574,607,608],{"class":587},"\"",[574,610,611],{"class":587},";\n",[574,613,615],{"class":576,"line":614},2,[574,616,618],{"emptyLinePlaceholder":617},true,"\n",[574,620,622,625,629,633],{"class":576,"line":621},3,[574,623,624],{"class":580},"export",[574,626,628],{"class":627},"spNyl"," interface",[574,630,632],{"class":631},"sBMFI"," OrderPlaced",[574,634,635],{"class":587}," {\n",[574,637,639,642,646,649,652],{"class":576,"line":638},4,[574,640,641],{"class":627},"  readonly",[574,643,645],{"class":644},"swJcz"," orderId",[574,647,648],{"class":587},":",[574,650,651],{"class":631}," string",[574,653,611],{"class":587},[574,655,657,659,662,664,666],{"class":576,"line":656},5,[574,658,641],{"class":627},[574,660,661],{"class":644}," sku",[574,663,648],{"class":587},[574,665,651],{"class":631},[574,667,611],{"class":587},[574,669,671,673,676,678,681],{"class":576,"line":670},6,[574,672,641],{"class":627},[574,674,675],{"class":644}," quantity",[574,677,648],{"class":587},[574,679,680],{"class":631}," number",[574,682,611],{"class":587},[574,684,686],{"class":576,"line":685},7,[574,687,688],{"class":587},"}\n",[574,690,692],{"class":576,"line":691},8,[574,693,618],{"emptyLinePlaceholder":617},[574,695,697,699,701,704,707,709],{"class":576,"line":696},9,[574,698,624],{"class":580},[574,700,628],{"class":627},[574,702,703],{"class":631}," OrderEventMap",[574,705,706],{"class":627}," extends",[574,708,592],{"class":631},[574,710,635],{"class":587},[574,712,714,716,718,721,723,725,727],{"class":576,"line":713},10,[574,715,641],{"class":627},[574,717,601],{"class":587},[574,719,720],{"class":604},"orders-placed",[574,722,608],{"class":587},[574,724,648],{"class":587},[574,726,632],{"class":631},[574,728,611],{"class":587},[574,730,732],{"class":576,"line":731},11,[574,733,688],{"class":587},[499,735,736,737,739],{},"Inject your typed queue producer and call ",[542,738,549],{},". It is fire-and-forget: it enqueues the message and\nreturns, so the request never waits on the slow part.",[534,741,744],{"className":567,"code":742,"filename":743,"language":570,"meta":540,"style":540},"export class OrdersController implements Controller\u003C\"\u002Forders\"> {\n  public constructor(private readonly queue: OrderQueue \u002F* …, log: OrderLog *\u002F) {}\n\n  public async place(action: Post\u003C\"\u002F\">): Promise\u003C{ orderId: string; queued: true }> {\n    const body = (await action.request.json()) as PlaceOrderBody;\n    const orderId = uuid.v7();\n\n    this.queue.publish(\"orders-placed\", { orderId, sku: body.sku, quantity: body.quantity });\n\n    action.response.status = 202;\n\n    return { orderId, queued: true };\n  }\n}\n","orders\u002Forders.controller.ts",[542,745,746,777,813,817,877,920,941,945,1004,1008,1031,1035,1057,1063],{"__ignoreMap":540},[574,747,748,750,753,756,759,762,765,767,770,772,775],{"class":576,"line":577},[574,749,624],{"class":580},[574,751,752],{"class":627}," class",[574,754,755],{"class":631}," OrdersController",[574,757,758],{"class":627}," implements",[574,760,761],{"class":631}," Controller",[574,763,764],{"class":587},"\u003C",[574,766,608],{"class":587},[574,768,769],{"class":604},"\u002Forders",[574,771,608],{"class":587},[574,773,774],{"class":587},">",[574,776,635],{"class":587},[574,778,779,782,785,788,791,794,798,800,803,807,810],{"class":576,"line":614},[574,780,781],{"class":627},"  public",[574,783,784],{"class":627}," constructor",[574,786,787],{"class":587},"(",[574,789,790],{"class":627},"private",[574,792,793],{"class":627}," readonly",[574,795,797],{"class":796},"sHdIc"," queue",[574,799,648],{"class":587},[574,801,802],{"class":631}," OrderQueue",[574,804,806],{"class":805},"sHwdD"," \u002F* …, log: OrderLog *\u002F",[574,808,809],{"class":587},")",[574,811,812],{"class":587}," {}\n",[574,814,815],{"class":576,"line":621},[574,816,618],{"emptyLinePlaceholder":617},[574,818,819,821,824,827,829,832,834,837,839,841,844,846,849,852,855,857,859,861,864,867,869,872,875],{"class":576,"line":638},[574,820,781],{"class":627},[574,822,823],{"class":627}," async",[574,825,826],{"class":644}," place",[574,828,787],{"class":587},[574,830,831],{"class":796},"action",[574,833,648],{"class":587},[574,835,836],{"class":631}," Post",[574,838,764],{"class":587},[574,840,608],{"class":587},[574,842,843],{"class":604},"\u002F",[574,845,608],{"class":587},[574,847,848],{"class":587},">):",[574,850,851],{"class":631}," Promise",[574,853,854],{"class":587},"\u003C{",[574,856,645],{"class":644},[574,858,648],{"class":587},[574,860,651],{"class":631},[574,862,863],{"class":587},";",[574,865,866],{"class":644}," queued",[574,868,648],{"class":587},[574,870,871],{"class":631}," true",[574,873,874],{"class":587}," }>",[574,876,635],{"class":587},[574,878,879,882,885,888,891,894,897,900,903,905,909,912,915,918],{"class":576,"line":656},[574,880,881],{"class":627},"    const",[574,883,884],{"class":591}," body",[574,886,887],{"class":587}," =",[574,889,890],{"class":644}," (",[574,892,893],{"class":580},"await",[574,895,896],{"class":591}," action",[574,898,899],{"class":587},".",[574,901,902],{"class":591},"request",[574,904,899],{"class":587},[574,906,908],{"class":907},"s2Zo4","json",[574,910,911],{"class":644},"()) ",[574,913,914],{"class":580},"as",[574,916,917],{"class":631}," PlaceOrderBody",[574,919,611],{"class":587},[574,921,922,924,926,928,931,933,936,939],{"class":576,"line":670},[574,923,881],{"class":627},[574,925,645],{"class":591},[574,927,887],{"class":587},[574,929,930],{"class":591}," uuid",[574,932,899],{"class":587},[574,934,935],{"class":907},"v7",[574,937,938],{"class":644},"()",[574,940,611],{"class":587},[574,942,943],{"class":576,"line":685},[574,944,618],{"emptyLinePlaceholder":617},[574,946,947,950,953,955,957,959,961,963,965,968,970,972,974,976,978,980,982,985,987,989,991,993,995,998,1000,1002],{"class":576,"line":691},[574,948,949],{"class":587},"    this.",[574,951,952],{"class":591},"queue",[574,954,899],{"class":587},[574,956,549],{"class":907},[574,958,787],{"class":644},[574,960,608],{"class":587},[574,962,720],{"class":604},[574,964,608],{"class":587},[574,966,967],{"class":587},",",[574,969,588],{"class":587},[574,971,645],{"class":591},[574,973,967],{"class":587},[574,975,661],{"class":644},[574,977,648],{"class":587},[574,979,884],{"class":591},[574,981,899],{"class":587},[574,983,984],{"class":591},"sku",[574,986,967],{"class":587},[574,988,675],{"class":644},[574,990,648],{"class":587},[574,992,884],{"class":591},[574,994,899],{"class":587},[574,996,997],{"class":591},"quantity",[574,999,595],{"class":587},[574,1001,809],{"class":644},[574,1003,611],{"class":587},[574,1005,1006],{"class":576,"line":696},[574,1007,618],{"emptyLinePlaceholder":617},[574,1009,1010,1013,1015,1018,1020,1023,1025,1029],{"class":576,"line":713},[574,1011,1012],{"class":591},"    action",[574,1014,899],{"class":587},[574,1016,1017],{"class":591},"response",[574,1019,899],{"class":587},[574,1021,1022],{"class":591},"status",[574,1024,887],{"class":587},[574,1026,1028],{"class":1027},"sbssI"," 202",[574,1030,611],{"class":587},[574,1032,1033],{"class":576,"line":731},[574,1034,618],{"emptyLinePlaceholder":617},[574,1036,1038,1041,1043,1045,1047,1049,1051,1054],{"class":576,"line":1037},12,[574,1039,1040],{"class":580},"    return",[574,1042,588],{"class":587},[574,1044,645],{"class":591},[574,1046,967],{"class":587},[574,1048,866],{"class":644},[574,1050,648],{"class":587},[574,1052,871],{"class":1053},"sfNiH",[574,1055,1056],{"class":587}," };\n",[574,1058,1060],{"class":576,"line":1059},13,[574,1061,1062],{"class":587},"  }\n",[574,1064,1066],{"class":576,"line":1065},14,[574,1067,688],{"class":587},[499,1069,1070,1073,1074,1077],{},[542,1071,1072],{},"OrderQueue"," is your producer — a one-line subclass of the transport that fixes its channel map (shown in\nthe next section). The ",[542,1075,1076],{},"202"," comes back before the handler runs.",[515,1079,1081],{"id":1080},"consume-a-channel","Consume a channel",[499,1083,1084,1085,1088,1089,1092],{},"A consumer is a class that declares ",[542,1086,1087],{},"implements QueueEventHandler\u003Cchannel, Payload>"," and a single\n",[542,1090,1091],{},"handle(payload)",". Its constructor is its dependency list — inject whatever it needs. The compiler reads\nthe channel from the first type argument and routes every message on it to this handler.",[534,1094,1097],{"className":567,"code":1095,"filename":1096,"language":570,"meta":540,"style":540},"import type { QueueEventHandler } from \"@heximon\u002Fqueue\";\nimport type { OrderPlaced } from \".\u002Forder-events\";\nimport { OrderLog } from \".\u002Forder-log\";\n\nexport class OrderPlacedHandler implements QueueEventHandler\u003C\"orders-placed\", OrderPlaced> {\n  public constructor(private readonly log: OrderLog) {}\n\n  public async handle(payload: OrderPlaced): Promise\u003Cvoid> {\n    this.log.record(payload);\n    await Promise.resolve();\n  }\n}\n","orders\u002Forder-placed.handler.ts",[542,1098,1099,1122,1145,1167,1171,1200,1223,1227,1259,1279,1295,1299],{"__ignoreMap":540},[574,1100,1101,1103,1105,1107,1110,1112,1114,1116,1118,1120],{"class":576,"line":577},[574,1102,581],{"class":580},[574,1104,584],{"class":580},[574,1106,588],{"class":587},[574,1108,1109],{"class":591}," QueueEventHandler",[574,1111,595],{"class":587},[574,1113,598],{"class":580},[574,1115,601],{"class":587},[574,1117,605],{"class":604},[574,1119,608],{"class":587},[574,1121,611],{"class":587},[574,1123,1124,1126,1128,1130,1132,1134,1136,1138,1141,1143],{"class":576,"line":614},[574,1125,581],{"class":580},[574,1127,584],{"class":580},[574,1129,588],{"class":587},[574,1131,632],{"class":591},[574,1133,595],{"class":587},[574,1135,598],{"class":580},[574,1137,601],{"class":587},[574,1139,1140],{"class":604},".\u002Forder-events",[574,1142,608],{"class":587},[574,1144,611],{"class":587},[574,1146,1147,1149,1151,1154,1156,1158,1160,1163,1165],{"class":576,"line":621},[574,1148,581],{"class":580},[574,1150,588],{"class":587},[574,1152,1153],{"class":591}," OrderLog",[574,1155,595],{"class":587},[574,1157,598],{"class":580},[574,1159,601],{"class":587},[574,1161,1162],{"class":604},".\u002Forder-log",[574,1164,608],{"class":587},[574,1166,611],{"class":587},[574,1168,1169],{"class":576,"line":638},[574,1170,618],{"emptyLinePlaceholder":617},[574,1172,1173,1175,1177,1180,1182,1184,1186,1188,1190,1192,1194,1196,1198],{"class":576,"line":656},[574,1174,624],{"class":580},[574,1176,752],{"class":627},[574,1178,1179],{"class":631}," OrderPlacedHandler",[574,1181,758],{"class":627},[574,1183,1109],{"class":631},[574,1185,764],{"class":587},[574,1187,608],{"class":587},[574,1189,720],{"class":604},[574,1191,608],{"class":587},[574,1193,967],{"class":587},[574,1195,632],{"class":631},[574,1197,774],{"class":587},[574,1199,635],{"class":587},[574,1201,1202,1204,1206,1208,1210,1212,1215,1217,1219,1221],{"class":576,"line":670},[574,1203,781],{"class":627},[574,1205,784],{"class":627},[574,1207,787],{"class":587},[574,1209,790],{"class":627},[574,1211,793],{"class":627},[574,1213,1214],{"class":796}," log",[574,1216,648],{"class":587},[574,1218,1153],{"class":631},[574,1220,809],{"class":587},[574,1222,812],{"class":587},[574,1224,1225],{"class":576,"line":685},[574,1226,618],{"emptyLinePlaceholder":617},[574,1228,1229,1231,1233,1236,1238,1241,1243,1245,1248,1250,1252,1255,1257],{"class":576,"line":691},[574,1230,781],{"class":627},[574,1232,823],{"class":627},[574,1234,1235],{"class":644}," handle",[574,1237,787],{"class":587},[574,1239,1240],{"class":796},"payload",[574,1242,648],{"class":587},[574,1244,632],{"class":631},[574,1246,1247],{"class":587},"):",[574,1249,851],{"class":631},[574,1251,764],{"class":587},[574,1253,1254],{"class":631},"void",[574,1256,774],{"class":587},[574,1258,635],{"class":587},[574,1260,1261,1263,1266,1268,1271,1273,1275,1277],{"class":576,"line":696},[574,1262,949],{"class":587},[574,1264,1265],{"class":591},"log",[574,1267,899],{"class":587},[574,1269,1270],{"class":907},"record",[574,1272,787],{"class":644},[574,1274,1240],{"class":591},[574,1276,809],{"class":644},[574,1278,611],{"class":587},[574,1280,1281,1284,1286,1288,1291,1293],{"class":576,"line":713},[574,1282,1283],{"class":580},"    await",[574,1285,851],{"class":631},[574,1287,899],{"class":587},[574,1289,1290],{"class":907},"resolve",[574,1292,938],{"class":644},[574,1294,611],{"class":587},[574,1296,1297],{"class":576,"line":731},[574,1298,1062],{"class":587},[574,1300,1301],{"class":576,"line":1037},[574,1302,688],{"class":587},[499,1304,1305,1306,1309,1310,1313],{},"The channel must be a ",[503,1307,1308],{},"string literal"," — the compiler turns it into the dispatch key at build time.\nSeveral handlers may bind the same channel; each runs when the channel drains. (",[542,1311,1312],{},"extends QueueEventHandler\u003C…>"," binds identically — use it when you want your own base class on top of a handler.)",[515,1315,1317],{"id":1316},"wire-it-into-a-module","Wire it into a module",[499,1319,1320,1321,1324,1325,1328,1329,1331],{},"List handlers under the module's ",[542,1322,1323],{},"queue: { handlers }"," key — never in ",[542,1326,1327],{},"providers",". That's how the compiler\nknows to route each class to its channel instead of treating it as a plain injectable. The producer\ntransport is bound in ",[542,1330,1327],{},"; anything a handler depends on stays an ordinary provider too.",[534,1333,1336],{"className":567,"code":1334,"filename":1335,"language":570,"meta":540,"style":540},"export class AppModule extends Module({\n  providers: [\n    OrderLog,\n    NetlifyAsyncWorkloadsPlatformSimulator,\n    {\n      \u002F\u002F In production: `new OrderQueue()`, and the platform delivers. In dev\u002FCI: publish through an\n      \u002F\u002F in-process stand-in so the same producer + consumer run locally, no platform required.\n      provide: OrderQueue,\n      useFactory: (simulator: NetlifyAsyncWorkloadsPlatformSimulator): OrderQueue =>\n        new OrderQueue(simulator.netlifyClient),\n    },\n  ],\n  http: { controllers: [OrdersController] },\n  queue: { handlers: [OrderPlacedHandler] },\n}) {}\n","app.module.ts",[542,1337,1338,1357,1367,1375,1382,1387,1392,1397,1408,1432,1449,1454,1461,1481,1500],{"__ignoreMap":540},[574,1339,1340,1342,1344,1347,1349,1352,1354],{"class":576,"line":577},[574,1341,624],{"class":580},[574,1343,752],{"class":627},[574,1345,1346],{"class":631}," AppModule",[574,1348,706],{"class":627},[574,1350,1351],{"class":907}," Module",[574,1353,787],{"class":591},[574,1355,1356],{"class":587},"{\n",[574,1358,1359,1362,1364],{"class":576,"line":614},[574,1360,1361],{"class":644},"  providers",[574,1363,648],{"class":587},[574,1365,1366],{"class":591}," [\n",[574,1368,1369,1372],{"class":576,"line":621},[574,1370,1371],{"class":591},"    OrderLog",[574,1373,1374],{"class":587},",\n",[574,1376,1377,1380],{"class":576,"line":638},[574,1378,1379],{"class":591},"    NetlifyAsyncWorkloadsPlatformSimulator",[574,1381,1374],{"class":587},[574,1383,1384],{"class":576,"line":656},[574,1385,1386],{"class":587},"    {\n",[574,1388,1389],{"class":576,"line":670},[574,1390,1391],{"class":805},"      \u002F\u002F In production: `new OrderQueue()`, and the platform delivers. In dev\u002FCI: publish through an\n",[574,1393,1394],{"class":576,"line":685},[574,1395,1396],{"class":805},"      \u002F\u002F in-process stand-in so the same producer + consumer run locally, no platform required.\n",[574,1398,1399,1402,1404,1406],{"class":576,"line":691},[574,1400,1401],{"class":644},"      provide",[574,1403,648],{"class":587},[574,1405,802],{"class":591},[574,1407,1374],{"class":587},[574,1409,1410,1413,1415,1417,1420,1422,1425,1427,1429],{"class":576,"line":696},[574,1411,1412],{"class":907},"      useFactory",[574,1414,648],{"class":587},[574,1416,890],{"class":587},[574,1418,1419],{"class":796},"simulator",[574,1421,648],{"class":587},[574,1423,1424],{"class":631}," NetlifyAsyncWorkloadsPlatformSimulator",[574,1426,1247],{"class":587},[574,1428,802],{"class":631},[574,1430,1431],{"class":627}," =>\n",[574,1433,1434,1437,1439,1442,1444,1447],{"class":576,"line":713},[574,1435,1436],{"class":587},"        new",[574,1438,802],{"class":907},[574,1440,1441],{"class":591},"(simulator",[574,1443,899],{"class":587},[574,1445,1446],{"class":591},"netlifyClient)",[574,1448,1374],{"class":587},[574,1450,1451],{"class":576,"line":731},[574,1452,1453],{"class":587},"    },\n",[574,1455,1456,1459],{"class":576,"line":1037},[574,1457,1458],{"class":591},"  ]",[574,1460,1374],{"class":587},[574,1462,1463,1466,1468,1470,1473,1475,1478],{"class":576,"line":1059},[574,1464,1465],{"class":644},"  http",[574,1467,648],{"class":587},[574,1469,588],{"class":587},[574,1471,1472],{"class":644}," controllers",[574,1474,648],{"class":587},[574,1476,1477],{"class":591}," [OrdersController] ",[574,1479,1480],{"class":587},"},\n",[574,1482,1483,1486,1488,1490,1493,1495,1498],{"class":576,"line":1065},[574,1484,1485],{"class":644},"  queue",[574,1487,648],{"class":587},[574,1489,588],{"class":587},[574,1491,1492],{"class":644}," handlers",[574,1494,648],{"class":587},[574,1496,1497],{"class":591}," [OrderPlacedHandler] ",[574,1499,1480],{"class":587},[574,1501,1503,1506,1509],{"class":576,"line":1502},15,[574,1504,1505],{"class":587},"}",[574,1507,1508],{"class":591},") ",[574,1510,1511],{"class":587},"{}\n",[499,1513,1514,1515,1518],{},"The producer itself is a one-liner — a named subclass of the transport that pins the channel map, so\n",[542,1516,1517],{},"publish(\"orders-placed\", …)"," stays statically checked:",[534,1520,1523],{"className":567,"code":1521,"filename":1522,"language":570,"meta":540,"style":540},"import { NetlifyAsyncWorkloadsQueue } from \"@heximon\u002Fqueue\u002Fnetlify\";\nimport type { OrderEventMap } from \".\u002Forder-events\";\n\nexport class OrderQueue extends NetlifyAsyncWorkloadsQueue\u003COrderEventMap> {}\n","orders\u002Forder-queue.ts",[542,1524,1525,1547,1569,1573],{"__ignoreMap":540},[574,1526,1527,1529,1531,1534,1536,1538,1540,1543,1545],{"class":576,"line":577},[574,1528,581],{"class":580},[574,1530,588],{"class":587},[574,1532,1533],{"class":591}," NetlifyAsyncWorkloadsQueue",[574,1535,595],{"class":587},[574,1537,598],{"class":580},[574,1539,601],{"class":587},[574,1541,1542],{"class":604},"@heximon\u002Fqueue\u002Fnetlify",[574,1544,608],{"class":587},[574,1546,611],{"class":587},[574,1548,1549,1551,1553,1555,1557,1559,1561,1563,1565,1567],{"class":576,"line":614},[574,1550,581],{"class":580},[574,1552,584],{"class":580},[574,1554,588],{"class":587},[574,1556,703],{"class":591},[574,1558,595],{"class":587},[574,1560,598],{"class":580},[574,1562,601],{"class":587},[574,1564,1140],{"class":604},[574,1566,608],{"class":587},[574,1568,611],{"class":587},[574,1570,1571],{"class":576,"line":621},[574,1572,618],{"emptyLinePlaceholder":617},[574,1574,1575,1577,1579,1581,1583,1585,1587,1590,1592],{"class":576,"line":638},[574,1576,624],{"class":580},[574,1578,752],{"class":627},[574,1580,802],{"class":631},[574,1582,706],{"class":627},[574,1584,1533],{"class":631},[574,1586,764],{"class":587},[574,1588,1589],{"class":631},"OrderEventMap",[574,1591,774],{"class":587},[574,1593,812],{"class":587},[499,1595,1596,1597,1600,1601,1604,1605,1608,1609,1611,1612,1615,1616,1619],{},"Enable the tier by adding ",[542,1598,1599],{},"new QueuePlugin()"," (from ",[542,1602,1603],{},"@heximon\u002Fqueue\u002Fcompiler",") to your\n",[542,1606,1607],{},"heximon.config.ts"," plugins list. A class listed under ",[542,1610,1323],{}," whose heritage names no\n",[542,1613,1614],{},"QueueEventHandler"," is constructed but never fires — an almost-always-missing ",[542,1617,1618],{},"implements QueueEventHandler\u003C…>"," clause.",[515,1621,1623],{"id":1622},"retry-and-validate","Retry and validate",[499,1625,1626,1627,1630,1631,1634,1635,1638,1639,1642],{},"Delivery is ",[503,1628,1629],{},"at-least-once",", so handlers should tolerate a retry. Opt into a per-handler retry policy\nwith an optional third type argument —\n",[542,1632,1633],{},"QueueEventHandler\u003C\"orders-placed\", OrderPlaced, { retry: { attempts: 3, delay: 200 } }>",", where ",[542,1636,1637],{},"attempts","\ncounts the first try and ",[542,1640,1641],{},"delay"," is milliseconds. Omit it to keep the default (retry contention only).",[499,1644,1645,1646,1649,1650,1657,1658,1661,1662,1665],{},"Opt into runtime payload validation by overriding ",[542,1647,1648],{},"getPayloadSchema()"," to return any\n",[1651,1652,1656],"a",{"href":1653,"rel":1654},"https:\u002F\u002Fstandardschema.dev",[1655],"nofollow","Standard Schema"," (zod, valibot, arktype). It runs once, before ",[542,1659,1660],{},"handle",", and\n",[503,1663,1664],{},"outside"," the retry loop — so a malformed payload is rejected instead of retried.",[534,1667,1669],{"className":567,"code":1668,"language":570,"meta":540,"style":540},"class ValidatingWarmer extends QueueEventHandler\u003C\"cache.warm\", { id: number }> {\n  public override handle(): void {}\n\n  public override getPayloadSchema(): StandardSchemaV1\u003C{ id: number }> {\n    return idSchema;\n  }\n}\n",[542,1670,1671,1707,1724,1728,1754,1763,1767],{"__ignoreMap":540},[574,1672,1673,1676,1679,1681,1683,1685,1687,1690,1692,1694,1696,1699,1701,1703,1705],{"class":576,"line":577},[574,1674,1675],{"class":627},"class",[574,1677,1678],{"class":631}," ValidatingWarmer",[574,1680,706],{"class":627},[574,1682,1109],{"class":631},[574,1684,764],{"class":587},[574,1686,608],{"class":587},[574,1688,1689],{"class":604},"cache.warm",[574,1691,608],{"class":587},[574,1693,967],{"class":587},[574,1695,588],{"class":587},[574,1697,1698],{"class":644}," id",[574,1700,648],{"class":587},[574,1702,680],{"class":631},[574,1704,874],{"class":587},[574,1706,635],{"class":587},[574,1708,1709,1711,1714,1716,1719,1722],{"class":576,"line":614},[574,1710,781],{"class":627},[574,1712,1713],{"class":627}," override",[574,1715,1235],{"class":644},[574,1717,1718],{"class":587},"():",[574,1720,1721],{"class":631}," void",[574,1723,812],{"class":587},[574,1725,1726],{"class":576,"line":621},[574,1727,618],{"emptyLinePlaceholder":617},[574,1729,1730,1732,1734,1737,1739,1742,1744,1746,1748,1750,1752],{"class":576,"line":638},[574,1731,781],{"class":627},[574,1733,1713],{"class":627},[574,1735,1736],{"class":644}," getPayloadSchema",[574,1738,1718],{"class":587},[574,1740,1741],{"class":631}," StandardSchemaV1",[574,1743,854],{"class":587},[574,1745,1698],{"class":644},[574,1747,648],{"class":587},[574,1749,680],{"class":631},[574,1751,874],{"class":587},[574,1753,635],{"class":587},[574,1755,1756,1758,1761],{"class":576,"line":656},[574,1757,1040],{"class":580},[574,1759,1760],{"class":591}," idSchema",[574,1762,611],{"class":587},[574,1764,1765],{"class":576,"line":670},[574,1766,1062],{"class":587},[574,1768,1769],{"class":576,"line":685},[574,1770,688],{"class":587},[515,1772,1774],{"id":1773},"dedup-redeliveries","Dedup redeliveries",[499,1776,1777,1778,1781,1782,1785,1786,1789,1790,1793,1794,1796],{},"Because delivery is at-least-once, a message can arrive twice. If handling it isn't naturally idempotent,\nadd ",[542,1779,1780],{},"QueueIdempotencyInterceptor"," from ",[542,1783,1784],{},"@heximon\u002Fqueue\u002Fidempotency"," under ",[542,1787,1788],{},"queue: { interceptors }"," — it\ndedups on the stable envelope id over a ",[542,1791,1792],{},"Storage"," backend, so a redelivery is dropped instead of\nre-run. See ",[1651,1795,185],{"href":186}," for the full picture.",[515,1798,1800],{"id":1799},"production-transports","Production transports",[499,1802,1803,1804,1807,1808,1811,1812,1815],{},"The dev transport is ",[542,1805,1806],{},"MemoryQueue",", in-process and zero-config. For production, bind the durable transport\nfor where you deploy — the handler and module wiring don't change, only the producer subclass does. ",[503,1809,1810],{},"Push","\ntransports let the platform deliver each message (no process to run); ",[503,1813,1814],{},"poll"," transports run a drain loop\ninside a long-lived Node\u002FBun\u002FDeno process.",[1817,1818,1819,1836],"table",{},[1820,1821,1822],"thead",{},[1823,1824,1825,1830,1833],"tr",{},[1826,1827,1829],"th",{"align":1828},"left","Platform",[1826,1831,1832],{"align":1828},"Subpath",[1826,1834,1835],{"align":1828},"Delivery",[1837,1838,1839,1853,1866,1878,1895,1908],"tbody",{},[1823,1840,1841,1845,1850],{},[1842,1843,1844],"td",{"align":1828},"Cloudflare Workers",[1842,1846,1847],{"align":1828},[542,1848,1849],{},"@heximon\u002Fqueue\u002Fcloudflare",[1842,1851,1852],{"align":1828},"push — the platform delivers a batch to the worker",[1823,1854,1855,1858,1863],{},[1842,1856,1857],{"align":1828},"Vercel Functions",[1842,1859,1860],{"align":1828},[542,1861,1862],{},"@heximon\u002Fqueue\u002Fvercel",[1842,1864,1865],{"align":1828},"push — to a dedicated function",[1823,1867,1868,1871,1875],{},[1842,1869,1870],{"align":1828},"Netlify Functions",[1842,1872,1873],{"align":1828},[542,1874,1542],{},[1842,1876,1877],{"align":1828},"push — to a generated workload consumer",[1823,1879,1880,1883,1888],{},[1842,1881,1882],{"align":1828},"SQL (pg \u002F mysql \u002F sqlite)",[1842,1884,1885],{"align":1828},[542,1886,1887],{},"@heximon\u002Fqueue\u002Fdrizzle",[1842,1889,1890,1891,1894],{"align":1828},"poll — a long-lived process; ",[542,1892,1893],{},"FOR UPDATE SKIP LOCKED"," on pg\u002Fmysql",[1823,1896,1897,1900,1905],{},[1842,1898,1899],{"align":1828},"AWS SQS",[1842,1901,1902],{"align":1828},[542,1903,1904],{},"@heximon\u002Fqueue\u002Fsqs",[1842,1906,1907],{"align":1828},"poll — long-polling consumer (also a push consumer for SQS-triggered Lambda)",[1823,1909,1910,1913,1918],{},[1842,1911,1912],{"align":1828},"Upstash Redis Streams",[1842,1914,1915],{"align":1828},[542,1916,1917],{},"@heximon\u002Fqueue\u002Fupstash",[1842,1919,1890,1920,1923,1924],{"align":1828},[542,1921,1922],{},"XREADGROUP"," \u002F ",[542,1925,1926],{},"XACK",[499,1928,1929,1930,1933,1934,1937,1938,1940,1941,1943,1944,899],{},"The SQL, SQS, and Upstash ",[503,1931,1932],{},"producers"," run anywhere with a global ",[542,1935,1936],{},"fetch"," (edge included); only their poll\nconsumers need a persistent process. Full per-platform wiring lives on the deploy pages —\n",[1651,1939,312],{"href":313},", ",[1651,1942,317],{"href":318},", and ",[1651,1945,322],{"href":323},[515,1947,1949],{"id":1948},"relation-to-integration-events","Relation to integration events",[499,1951,1952,1953,1955,1956,1960,1961,1963,1964,1967],{},"A raw ",[542,1954,1614],{}," is the low-level tier. For the common case — ",[1957,1958,1959],"em",{},"\"a domain thing happened, react to\nit across modules or services\""," — reach for the typed ",[1651,1962,243],{"href":244},"\ntier instead: a producer publishes through a typed event class injected by class identity, and a consumer\nimplements ",[542,1965,1966],{},"IntegrationEventHandler",". Both ride this exact queue, so everything above — retry, validation,\nthe idempotency interceptor, the durable transports — applies to that tier unchanged.",[515,1969,1971],{"id":1970},"see-also","See also",[1973,1974,1975,1981,1989,1998,2004,2026],"ul",{},[1976,1977,1978,1980],"li",{},[1651,1979,243],{"href":244}," — the typed event producer over this\ntransport: publish by class identity, consume one class per handler, plus the transactional outbox and\ncross-service fan-out.",[1976,1982,1983,1985,1986,1988],{},[1651,1984,185],{"href":186}," — ",[542,1987,1780],{},", for deduping redelivered\nmessages under at-least-once delivery.",[1976,1990,1991,1993,1994,1997],{},[1651,1992,146],{"href":147}," — the in-process ",[542,1995,1996],{},"EventBus",", for a side effect that doesn't need to\ncross a process boundary or survive a restart.",[1976,1999,2000,2003],{},[1651,2001,2002],{"href":157},"Scheduled jobs"," — the sibling tier for recurring cron work.",[1976,2005,2006,2011,2012,2014,2015,2018,2019,2021,2022,2025],{},[1651,2007,2010],{"href":2008,"rel":2009},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fheximon\u002Ftree\u002Fmain\u002Fexamples\u002Fgap\u002Fedge-platforms\u002Fnetlify-queue",[1655],"Example: Netlify queue","\n— a raw ",[542,2013,1614],{}," end to end: ",[542,2016,2017],{},"POST \u002Forders"," publishes and returns ",[542,2020,1076],{},", the handler fulfils the\norder off the queue, ",[542,2023,2024],{},"GET \u002Forders"," reads it back.",[1976,2027,2028,2033,2034,899],{},[1651,2029,2032],{"href":2030,"rel":2031},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fheximon\u002Ftree\u002Fmain\u002Fexamples\u002Fladder\u002FL08-queue",[1655],"Example: L08 — queue","\n— the integration-events tier over the in-memory queue: a sign-up endpoint queues a templated welcome\nemail while the request returns ",[542,2035,2036],{},"201",[2038,2039,2040],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":540,"searchDepth":614,"depth":614,"links":2042},[2043,2044,2045,2046,2047,2048,2049,2050,2051],{"id":517,"depth":614,"text":518},{"id":553,"depth":614,"text":554},{"id":1080,"depth":614,"text":1081},{"id":1316,"depth":614,"text":1317},{"id":1622,"depth":614,"text":1623},{"id":1773,"depth":614,"text":1774},{"id":1799,"depth":614,"text":1800},{"id":1948,"depth":614,"text":1949},{"id":1970,"depth":614,"text":1971},"Move slow work off the request path onto durable channels — the Queue producer port, QueueEventHandler consumers under queue { handlers }, per-handler retry and payload validation, MemoryQueue in dev, and a durable transport per platform.","md",null,{},{"icon":154},{"title":151,"description":2052},"eU22HNBCdy68vp7_B-h5MuE-PtnmI57ZBYPhRn7rm7Y",[2060,2062],{"title":146,"path":147,"stem":148,"description":2061,"icon":149,"children":-1},"Decouple features with events across three tiers — the in-process EventBus, EventHandler and NotificationHandler, and domain events on aggregates with DomainEvents.emitFrom.",{"title":156,"path":157,"stem":158,"description":2063,"icon":159,"children":-1},"Run work on a wall-clock cron schedule with ScheduledHandler — a process-local timer on Node, the platform cron trigger on Cloudflare, validated at build time.",1783300761903]