Skip to content

Delayed reminders

Some background tasks need to run after a specific delay. For example:

  • Sending a “Welcome” tips email 24 hours after a user signs up.
  • Triggering a billing warning email exactly 3 days before a subscription expires.
  • Executing an automatic database clean-up task at a scheduled date and time.

Layeron Queue supports future scheduling via delaySeconds (for relative delays from the moment of sending) and deliverAt (for absolute dates/times).

This example demonstrates a user sign-up flow where we immediately send a verification email, then schedule a welcome follow-up email to be sent exactly 24 hours (86,400 seconds) later.

Terminal window
import { backend } from "@layeron/core"
import { queue } from "@layeron/modules"
const app = backend()
// 1. Declare the notification queue
const notificationQueue = queue({
name: "notifications",
retry: {
maxAttempts: 3,
backoff: "fixed",
initialDelaySeconds: 10,
},
})
app.use(notificationQueue)
// 2. User Sign-up Route
app.post("/users/signup", async (request) => {
const body = await request.json() as { email: string; name: string }
const userId = crypto.randomUUID()
// Perform database registration...
await registerUserInDb(userId, body.email, body.name)
// A. Immediately enqueue an instant task to send a Verification Email
await notificationQueue.send({
userId,
type: "verification_email",
recipient: body.email,
})
// B. Enqueue a task to send a Welcome Email delayed by exactly 24 hours (86,400 seconds)
await notificationQueue.send(
{
userId,
type: "welcome_tips",
recipient: body.email,
},
{
delaySeconds: 86400, // 24 hours delay
},
)
// C. Alternatively, schedule an action for a specific absolute future Date
const billingDate = new Date()
billingDate.setDate(billingDate.getDate() + 30) // 30 days from now
await notificationQueue.send(
{
userId,
type: "billing_invoice_generation",
recipient: body.email,
},
{
deliverAt: billingDate, // Absolute time scheduling
},
)
return Response.json({
status: "registered",
userId,
}, { status: 201 })
})
// 3. Background Notification Handler
notificationQueue.consume(async (message) => {
const { type, recipient, userId } = message.payload
console.log(`[Queue] Executing notification [${type}] for recipient: ${recipient}`)
if (type === "verification_email") {
await sendVerificationLink(recipient, userId)
} else if (type === "welcome_tips") {
await sendWelcomeTips(recipient)
} else if (type === "billing_invoice_generation") {
await generateAndMailInvoice(recipient, userId)
}
})
// Mock helper functions
async function registerUserInDb(id: string, email: string, name: string) {}
async function sendVerificationLink(email: string, userId: string) {}
async function sendWelcomeTips(email: string) {}
async function generateAndMailInvoice(email: string, userId: string) {}
  1. Relative Delays with delaySeconds: Using delaySeconds: 86400 keeps the message unavailable to consumers for 24 hours.
  2. Absolute Scheduling with deliverAt: Passing a standard JavaScript Date object under the deliverAt option lets you set a precise target time. Layeron converts the date into an absolute UTC timestamp and delivers the message when that time is reached.
  3. Queue Reusability: A single queue can handle different message types. By adding a type discriminator (e.g., "verification_email" vs "welcome_tips") in the payload, your single consumer handler can cleanly route work to specialized services.