Ploy
Ploy
Next.js

Queues

Process background jobs in your Next.js app with Ploy queues.

Queues

Add message queues to your Next.js application for background job processing.

Configuration

Add a queue binding in your ploy.yaml:

ploy.yaml
kind: dynamic
build: pnpm build
out: dist
queue:
  TASKS: tasks

Generate types:

pnpm ploy types

Sending Messages

Send messages to the queue from API routes or Server Actions:

app/api/queue/route.ts
import { NextResponse } from "next/server";
import { getPloyContext } from "@meetploy/nextjs";

export async function POST(request: Request) {
	const { env } = getPloyContext();
	const body = await request.json();

	const { messageId } = await env.TASKS.send({
		action: body.action,
		data: body.data,
	});

	return NextResponse.json({ success: true, messageId });
}

Send with Delay

const { messageId } = await env.TASKS.send(
	{ action: "send-reminder" },
	{ delaySeconds: 3600 }, // 1 hour delay
);

Batch Send

const { messageIds } = await env.TASKS.sendBatch([
	{ payload: { action: "task-1" } },
	{ payload: { action: "task-2" } },
	{ payload: { action: "task-3" } },
]);

Message Handler

Create a ploy.ts file in your app directory to handle incoming messages:

app/ploy.ts
export default {
	async message(
		event: QueueMessageEvent,
		env: PloyEnv,
		ctx: ExecutionContext,
	): Promise<void> {
		console.log("Processing message:", {
			id: event.id,
			queue: event.queueName,
			payload: event.payload,
			attempt: event.attempt,
		});

		const payload = event.payload as { action: string; data?: unknown };

		switch (payload.action) {
			case "send-email":
				// Process email sending
				break;
			case "generate-report":
				// Generate report
				break;
			default:
				console.log("Unknown action:", payload.action);
		}
	},
} satisfies Ploy;

Messages that throw an error are automatically retried with exponential backoff.

Complete Example

Here's a complete example with database integration:

app/ploy.ts
export default {
	async message(
		event: QueueMessageEvent,
		env: PloyEnv,
		ctx: ExecutionContext,
	): Promise<void> {
		const payload = event.payload as { action: string; data: unknown };

		// Store processed message in database
		await env.DB.prepare(
			"INSERT INTO processed_messages (message_id, payload, processed_at) VALUES (?, ?, ?)",
		)
			.bind(event.id, JSON.stringify(payload), new Date().toISOString())
			.run();

		console.log("Message processed:", event.id);
	},
} satisfies Ploy;

Local Development

During development, the local Ploy dashboard at http://localhost:4000 lets you:

  • View pending and processed messages
  • Manually retry failed messages
  • Inspect message payloads

Next Steps

How is this guide?

Last updated on