This site is not affiliated with or endorsed by Cloudflare, Inc. It showcases deployable experiments across most Cloudflare products.
Stateful & Async

Queue Job Visualizer

Cloudflare Queues producer/consumer with KV-backed job status and simulated retries - visual job queue reference

Enqueue simulated jobs over HTTP, process them asynchronously with a Queues consumer, and track status transitions in KV (queued → processing → done / failed). The consumer simulates ~35% failure rate and retries via message.retry().

Features

  • POST /jobs - Enqueue a resize or fetch job
  • GET /jobs/:id - Poll job status from KV
  • Simulated failures - Consumer retries up to 3 attempts before marking failed
  • KV state machine - Full transition history on each job record

API Reference

POST /jobs

Enqueue a new job.

Prop

Type

Example Request

curl -X POST "https://your-worker.workers.dev/jobs" \
  -H "Content-Type: application/json" \
  -d '{"type":"fetch","target":"https://example.com/image.png"}'

Success Response (201)

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "type": "fetch",
  "target": "https://example.com/image.png",
  "status": "queued",
  "attempts": 0,
  "enqueuedAt": "2025-06-20T12:00:00.000Z",
  "updatedAt": "2025-06-20T12:00:00.000Z"
}

Error Codes

  • 400 - Invalid JSON (INVALID_BODY), type (INVALID_TYPE), or target (INVALID_TARGET)

GET /jobs/:id

Returns the current job record from KV.

Example Request

curl "https://your-worker.workers.dev/jobs/550e8400-e29b-41d4-a716-446655440000"

Success Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "type": "fetch",
  "target": "https://example.com/image.png",
  "status": "done",
  "attempts": 1,
  "result": "Fetched https://example.com/image.png (simulated)",
  "enqueuedAt": "2025-06-20T12:00:00.000Z",
  "updatedAt": "2025-06-20T12:01:00.000Z"
}

Error Codes

  • 404 - Job not found (NOT_FOUND)

Status may stay queued or processing briefly until the queue consumer runs. Poll until done or failed.

Use Cases

  • Learn Queues producer (send) and consumer (queue() handler) setup
  • Visualize async job lifecycles with KV-backed status
  • Demonstrate retry semantics with message.retry() and message.ack()

Limitations

  • Jobs are simulated; no actual image resize or fetch occurs
  • Failure rate is deterministic per job id + attempt (demo only)
  • Requires KV namespace and Queue configured in wrangler.json

Use in your project

Copy these files into an existing Worker. Prefer Deployment to try the full experiment first. Source: apps/experiments/queue-job-visualizer.

DependenciesNoneBindingsKV, QueuesPlatformWorkers runtime
import type { Env, JobMessage, JobRecord, JobStatus, JobType } from "../types/env";import { JOB_TTL_SECONDS } from "../constants/defaults";function jobKey(id: string): string {  return `job:${id}`;}export async function saveJob(env: Env, record: JobRecord): Promise<void> {  await env.JOBS.put(jobKey(record.id), JSON.stringify(record), {    expirationTtl: JOB_TTL_SECONDS,  });}export async function getJob(env: Env, id: string): Promise<JobRecord | null> {  const raw = await env.JOBS.get(jobKey(id));  if (!raw) return null;  return JSON.parse(raw) as JobRecord;}export async function updateJobStatus(  env: Env,  id: string,  status: JobStatus,  patch: Partial<JobRecord> = {}): Promise<JobRecord | null> {  const existing = await getJob(env, id);  if (!existing) return null;  const updated: JobRecord = {    ...existing,    ...patch,    status,    updatedAt: new Date().toISOString(),  };  await saveJob(env, updated);  return updated;}export function buildJobRecord(message: JobMessage): JobRecord {  return {    id: message.id,    type: message.type,    target: message.target,    status: "queued",    attempts: 0,    enqueuedAt: message.enqueuedAt,    updatedAt: message.enqueuedAt,  };}export function validateJobType(value: unknown): JobType | null {  return value === "resize" || value === "fetch" ? value : null;}export function validateTarget(value: unknown): string | null {  if (typeof value !== "string") return null;  const trimmed = value.trim();  if (!trimmed || trimmed.length > 500) return null;  return trimmed;}

Deployment

Click the deploy button

Deploy to Cloudflare Workers

Configure KV and Queue

Create a KV namespace bound as JOBS and a queue named queue-job-visualizer.

Test your deployment

curl -X POST "https://your-worker.workers.dev/jobs" \
  -H "Content-Type: application/json" \
  -d '{"type":"resize","target":"photo.png"}'

Local Development

cd apps/experiments/queue-job-visualizer
npm install
npm run dev

Configuration

BindingPurpose
JOBS_QUEUECloudflare Queue producer/consumer
JOBSKV namespace for job status records

Cloudflare Features Used

On this page