# ADR-0007：工作佇列用 PostgreSQL，不引入 Redis

已採用

## 狀態

已採用

## 背景

FFmpeg 轉檔必須離開 Fastify 的行程，因此需要一個工作佇列。業界的預設答案通常是 Redis 加上 BullMQ 之類的函式庫。

## 決策

工作佇列就是 PostgreSQL 的一張表，用 `SELECT ... FOR UPDATE SKIP LOCKED` 取件。

**這個 MVP 不引入 Redis。**

## 理由

**`FOR UPDATE SKIP LOCKED` 就是為這件事設計的。** 它是 PostgreSQL 內建的佇列原語：取件的交易鎖住那一列，其他工作者直接跳過去拿下一件。不需要輪詢衝突，也不需要分散式鎖。

**工作量級完全不需要 Redis。** 這是數位看板系統，不是影片平台。一天可能有幾十次上傳，尖峰也就是幾百件工作。PostgreSQL 在這個量級下連暖身都算不上。

**少一個要維運的東西。** 加上 Redis 就要多一個容器、多一組健康檢查、多一份備份策略、多一個會壞掉的地方。而且 Redis 預設不持久化——工作佇列放在會遺失的儲存裡，需要額外的設計才能保證不掉件。

**交易一致性是免費的。** 「建立素材紀錄」與「排入轉檔工作」在同一個交易裡完成。用 Redis 就是跨兩個系統的寫入，必須自己處理其中一邊失敗的情況。

**Server 只需要一個外部相依。** 這對想自架的客戶是很實際的差別。

## 後果

- 取件是輪詢的（預設每 2 秒），不是即時推播。對於本來就要跑好幾分鐘的轉檔工作，兩秒的延遲毫無意義。
- 工作表會成長，需要定期清理已完成的紀錄。
- 高頻率的短工作會在資料庫上產生可觀的負載。如果未來出現那種工作型態，這個決定就該重新評估。

## 何時該重新評估

- 工作量進入每秒數百件的等級。
- 出現需要毫秒級延遲的工作型態。
- 資料庫的佇列查詢在監控上開始成為熱點。

在那之前，多一個中介軟體只會增加維運負擔，換不到任何實際的好處。

## 替代方案

**Redis 加 BullMQ**：功能完整，但引入了一個新的有狀態元件，而且需要額外設計才能保證不掉件。

**RabbitMQ / Kafka**：這個規模下完全是過度設計。

**在 Fastify 裡直接跑**：轉檔期間 API 完全沒有回應，而且無法獨立擴充轉檔能力。
