Bỏ qua

Decision Framework

Queue vs Cron: Khi nào dùng gì?

Fundamental Difference

┌─────────────────────────────────────────────────────────────┐
│                    QUEUE vs CRON                             │
├────────────────────────────┬────────────────────────────────┤
│          QUEUE             │            CRON                │
├────────────────────────────┼────────────────────────────────┤
│  Event-driven              │  Time-driven                   │
│  "Do this when triggered"  │  "Do this at specific time"   │
│  Async processing          │  Scheduled execution          │
│  Variable load             │  Predictable load             │
└────────────────────────────┴────────────────────────────────┘

Decision Flowchart: Queue

┌─────────────────────────────────────────────────────────────┐
│                  WHEN TO USE QUEUE?                          │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  Is the task triggered by a user action or event?    │   │
│  └────────────────────────┬─────────────────────────────┘   │
│                           │                                  │
│                    YES ───┴─── NO                           │
│                     │         │                             │
│                     ▼         ▼                             │
│               Consider     Consider CRON                    │
│                QUEUE                                        │
│                     │                                       │
│                     ▼                                       │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  Does it need to complete after HTTP response?       │   │
│  └────────────────────────┬─────────────────────────────┘   │
│                           │                                  │
│                    YES ───┴─── NO                           │
│                     │         │                             │
│                     ▼         ▼                             │
│                  QUEUE     Sync OK                          │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Queue Use Cases

Trigger Example Why Queue?
User signup Send welcome email Don't block registration
Order placed Process payment Retry if fails
File uploaded Generate thumbnail Heavy processing
Comment posted Send notification Multiple recipients
Form submitted Validate data External API calls

Decision Flowchart: Cron

┌─────────────────────────────────────────────────────────────┐
│                  WHEN TO USE CRON?                           │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  Does the task need to run at specific times?        │   │
│  └────────────────────────┬─────────────────────────────┘   │
│                           │                                  │
│                    YES ───┴─── NO                           │
│                     │         │                             │
│                     ▼         ▼                             │
│               Consider     Consider QUEUE                   │
│                CRON        or Sync                          │
│                     │                                       │
│                     ▼                                       │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  Is it independent of user actions?                  │   │
│  └────────────────────────┬─────────────────────────────┘   │
│                           │                                  │
│                    YES ───┴─── NO                           │
│                     │         │                             │
│                     ▼         ▼                             │
│                  CRON     Maybe Queue                       │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Cron Use Cases

Schedule Example Why Cron?
Daily 2AM Cleanup old data Off-peak maintenance
Hourly Update statistics Regular aggregation
Daily 9AM Send digest emails User expectation
Weekly Generate reports Scheduled delivery
Monthly Archive old records Periodic maintenance

Decision Flowchart: Platform Selection

For Queue

┌─────────────────────────────────────────────────────────────┐
│              SUPABASE vs CLOUDFLARE QUEUE                    │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  Does consumer need complex DB queries/transactions? │   │
│  └────────────────────────┬─────────────────────────────┘   │
│                           │                                  │
│               YES ────────┴──────── NO                      │
│                │                     │                      │
│                ▼                     ▼                      │
│           Supabase            ┌───────────────────────┐    │
│             pgmq              │  High throughput      │    │
│                               │  (>1000 msg/min)?     │    │
│                               └───────────┬───────────┘    │
│                                           │                 │
│                              YES ─────────┴──────── NO     │
│                               │                     │      │
│                               ▼                     ▼      │
│                          Cloudflare            Either OK   │
│                            Queue                           │
│                                                              │
└─────────────────────────────────────────────────────────────┘

For Cron

┌─────────────────────────────────────────────────────────────┐
│              SUPABASE vs CLOUDFLARE CRON                     │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  Is task primarily database operations?              │   │
│  └────────────────────────┬─────────────────────────────┘   │
│                           │                                  │
│               YES ────────┴──────── NO                      │
│                │                     │                      │
│                ▼                     ▼                      │
│           Supabase            ┌───────────────────────┐    │
│           pg_cron             │  Needs external APIs? │    │
│                               └───────────┬───────────┘    │
│                                           │                 │
│                              YES ─────────┴──────── NO     │
│                               │                     │      │
│                               ▼                     ▼      │
│                          Cloudflare          pg_cron OK    │
│                         Cron Triggers                      │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Complete Decision Matrix

┌─────────────────────────────────────────────────────────────────────┐
│                      COMPLETE DECISION MATRIX                        │
├────────────────────┬────────────────────┬───────────────────────────┤
│    Scenario        │   Technology       │   Platform                │
├────────────────────┼────────────────────┼───────────────────────────┤
│ Email after signup │ Queue              │ Cloudflare (external API) │
│ Payment processing │ Queue              │ Cloudflare (retry needed) │
│ Webhook delivery   │ Queue              │ Cloudflare (external API) │
│ Order + notify     │ Queue              │ Supabase (transactional)  │
│ Thumbnail gen      │ Queue              │ Cloudflare (compute)      │
├────────────────────┼────────────────────┼───────────────────────────┤
│ Cleanup old data   │ Cron               │ Supabase (DB operation)   │
│ Daily digest       │ Cron               │ Cloudflare (email API)    │
│ Update statistics  │ Cron               │ Supabase (aggregation)    │
│ Sync external data │ Cron               │ Cloudflare (API calls)    │
│ Generate reports   │ Cron               │ Supabase (DB queries)     │
├────────────────────┼────────────────────┼───────────────────────────┤
│ Batch processing   │ Cron + Queue       │ CF Cron → CF Queue        │
│ Scheduled notif    │ Cron + Queue       │ pg_cron → CF Queue        │
│ DB maintenance +   │ Cron + Queue       │ pg_cron → pgmq            │
│   notify admin     │                    │                           │
└────────────────────┴────────────────────┴───────────────────────────┘

Quick Reference Card

Use QUEUE when:

✅ User action triggers async work
✅ Need retry on failure
✅ Want to respond fast to user
✅ Variable, unpredictable load
✅ Multiple consumers possible
✅ Decoupled architecture

Use CRON when:

✅ Time-based execution required
✅ Maintenance tasks
✅ Report generation
✅ Data synchronization
✅ Predictable, scheduled load
✅ No user waiting for result

Use Supabase (pgmq/pg_cron) when:

✅ Task is database-centric
✅ Need ACID transactions
✅ Complex SQL operations
✅ Data locality matters
✅ Included cost preference

Use Cloudflare (Queue/Cron) when:

✅ External API calls
✅ High throughput needed
✅ Complex JavaScript logic
✅ Global execution
✅ Workers integration

Anti-patterns to Avoid

❌ Wrong: Heavy DB work in Cloudflare Cron

// ❌ Multiple API calls for DB-heavy task
export default {
  async scheduled() {
    // This should be pg_cron!
    const { data } = await supabase.from('table').select('*');
    for (const row of data) {
      await supabase.from('table').update({ ... }).eq('id', row.id);
    }
  }
};

❌ Wrong: External API in pg_cron

-- ❌ Complex HTTP in SQL
SELECT cron.schedule('send-emails', '0 * * * *',
  'SELECT http_post(...) FROM users WHERE ...'
);
-- Hard to debug, error handling difficult

❌ Wrong: Queue for scheduled tasks

// ❌ Queue with artificial delay
await queue.send(
  { task: 'daily-report' },
  { delay: 86400 }  // 24 hours
);
// Use Cron instead!

❌ Wrong: Cron for event-driven

-- ❌ Polling for new records
SELECT cron.schedule('check-new-orders', '* * * * *',
  'SELECT process_new_orders()'
);
-- Use Queue triggered by INSERT instead!

Tổng kết

The Simple Rule

Event-driven? ──────────▶ QUEUE
Time-driven?  ──────────▶ CRON
Database work? ─────────▶ SUPABASE
External APIs? ─────────▶ CLOUDFLARE

Hybrid is OK

  • Cron triggers Queue (scheduled batches)
  • Queue processes with Cron fallback (recovery)
  • Both platforms can work together

Q&A

  1. Có scenario nào trong dự án khó quyết định?
  2. Đã thử hybrid approach chưa?
  3. Còn use case nào cần discuss?