You need to send a welcome email after signup. Process a payment in the background. Generate a PDF and notify the user. So you set up Redis, install BullMQ, write a worker process, configure a separate deploy target, and build monitoring around it. All for a function you already wrote.
Same function. Runs in the background.
You write this
const sendWelcomeEmail = pikkuFunc({
input: z.object({ userId: z.string() }),
func: async ({ db, email }, { userId }) => {
const user = await db.users.find(userId)
await email.send({
to: user.email,
template: 'welcome',
})
},
permissions: { service: isInternalService },
})
// Process in the background
wireQueueWorker({ queue: 'emails', func: sendWelcomeEmail })
// Also callable via HTTP for testing
wireHTTP({ method: 'post', route: '/admin/send-welcome', func: sendWelcomeEmail })
One function. Runs as a queue worker and an API endpoint. Same code.
Fabric handles
Managed queue infra
No Redis to run. No worker processes to deploy. Fabric manages the queue.
Retries + dead-letter
Failed jobs retry with backoff. Permanently failed jobs go to dead-letter for inspection.
Job visibility
See pending, active, completed, and failed jobs. Full traces per job.
Same auth model
Queue workers enforce the same permissions as your API. No backdoor execution.
Every job is tracked.
Stop managing queue infrastructure.
Write the function. Wire it to a queue. Deploy.