Back to Blog
Architecture6 min read2026-05-01

Background Jobs in the Cloud: Cronjobs vs Workers vs Event Queues

Scheduled tasks, background workers, and event-driven queues all solve different problems. Here's how to pick the right one — and how each runs on PandaStack.

# Background Jobs in the Cloud: Cronjobs vs Workers vs Event Queues

Every non-trivial app has background processing. Sending an email after signup, resizing uploaded images, generating a monthly invoice, syncing data from an external API — none of these should happen inside an HTTP request handler. But how you process them matters.

There are three main patterns, and they're not interchangeable.

1. Cronjobs (Scheduled Tasks)

What they are: Tasks that run on a schedule, regardless of user activity.

Examples:

  • Send weekly digest emails every Monday at 8am
  • Sync data from a third-party API every hour
  • Clean up expired sessions every day at midnight
  • Generate monthly billing reports on the first of each month

When to use them: When the task is time-based, not event-triggered. The schedule is the trigger.

On PandaStack: Native cronjob support with container-based execution:

panda cronjob create \
  --name "weekly-digest" \
  --image your-org/mailer:latest \
  --schedule "0 8 * * 1" \
  --env MAIL_API_KEY=xxx

Each run is logged. You can set alerts for failed executions. Manual trigger with panda cronjob run --name weekly-digest.

2. Background Workers

What they are: Long-running processes that pick tasks off a queue and execute them.

Examples:

  • Processing uploaded files after a user submits them
  • Sending transactional emails triggered by user actions
  • Resizing images, generating thumbnails
  • Running expensive computations that would time out in an HTTP request

When to use them: When a user action triggers processing that takes more than a second or two.

The pattern:

// API handler — fast
app.post('/uploads', async (req, res) => {
  const job = await queue.add({ fileId: req.file.id })
  res.json({ jobId: job.id }) // return immediately
})

// Worker process — runs separately
queue.process(async (job) => {
  const file = await getFile(job.data.fileId)
  await resize(file)
  await notify(file.userId)
})

On PandaStack: Deploy the worker as a separate Container App project pointing at the same Docker image but with a different start command. It shares the same database and Redis queue.

3. Event Queues

What they are: Message brokers (RabbitMQ, SQS, Kafka) that decouple producers from consumers.

Examples:

  • Order placed → inventory service, notification service, analytics service all process independently
  • User signup → onboarding email, welcome gift, CRM sync happen in parallel
  • Payment succeeded → update subscription, provision feature access, send receipt

When to use them: When multiple systems need to react to the same event, or when you need guaranteed delivery and retry semantics.

The pattern:

// Producer (in your API)
await rabbitMQ.publish('user.signed_up', { userId, email })

// Consumer 1 (email service)
rabbitMQ.subscribe('user.signed_up', async (msg) => {
  await sendWelcomeEmail(msg.email)
})

// Consumer 2 (analytics service)
rabbitMQ.subscribe('user.signed_up', async (msg) => {
  await trackSignup(msg.userId)
})

On PandaStack: Connect to any external RabbitMQ or use a managed queue service via environment variables. Each consumer is a separate container project.

Decision Framework

TriggerPattern
Time-based scheduleCronjob
User action, needs processing < 30sBackground worker with queue
User action, multiple systems need to knowEvent queue
One-off task, triggered manuallyCronjob with manual run

The Common Mistake

Putting everything in cronjobs. Cronjobs are tempting because they're simple, but a cronjob checking "are there any unprocessed uploads?" every minute is worse than a queue that triggers processing immediately when an upload arrives.

Use the trigger that matches the event. Time → cron. Action → queue.

Full docs: [docs.pandastack.io](https://docs.pandastack.io).

Ready to deploy?

Start free on PandaStack — no credit card required.

Start free on PandaStack

See also