Most job queues forget your types at the queue boundary A Promise chain in TypeScript is a thing of beauty: const summary = await fetchUser ( id ) . then (( user ) => fetchOrders ( user . id )) . then (( orders ) => summarize ( orders )); // ^^^^^^ Order[] Enter fullscreen mode Exit fullscreen mode Each step's input is typed by the previous step's output. Try to call fetchOrders(user.something_that_doesnt_exist) and the compiler stops you. Misuse the summary variable at the end and the compiler stops you. Now the typical background-job version of the same thing: await queue . add ( " fetch-user " , { id }); // ... worker processes fetch-user, then enqueues fetch-orders ... // ... worker processes fetch-orders, then enqueues summarize ... Enter fullscreen mode Exit fullscreen mode The compiler sees string (the type name) and unknown (the payload). Whatever the fetch-user handler returned, nothing checks that the input to fetch-orders matches it.…