Tuần trước có một founder nhắn tôi hỏi liệu có nên gỡ Sidekiq ra khỏi một Rails app sáu tháng tuổi để chuyển sang Solid Queue không, vì bạn ấy đọc trên Hacker News thấy Rails 8 đã chính thức hoá lựa chọn này. Tôi trả lời như tôi vẫn trả lời hầu hết mọi người hỏi câu tương tự: có thể, nhưng chưa phải lúc, và chắc chắn không phải vì cái lý do bạn đang nghĩ trong đầu. Lý do để chuyển không phải là “Redis dở” cũng không phải “Basecamp ship rồi nên mình theo”. Lý do là vận hành, và phần lớn app không có áp lực vận hành đủ lớn để xứng đáng với sự xáo trộn của việc đổi. Bài này là cái rubric tôi dùng khi khách hỏi. Nó có quan điểm rõ ràng, cố tình ít case study, và kết thúc bằng một luận điểm có thể phản biện về chỗ ranh giới nằm ở đâu.

Chúng ta đang so sánh cái gì

Sidekiq là background job processor cho Ruby, dùng Redis làm backend, do Mike Perham phát hành lần đầu năm 2012. Nó chạy jobs trong các thread bên trong một process riêng, lưu queues, retries và scheduled jobs trong Redis. Bản OSS miễn phí; bản Pro và Enterprise tính phí, thêm các tính năng như unique jobs, batches, và rolling restarts.

Solid Queue là job runner dùng database làm backend, được extract từ HEY và ship bởi 37signals. Nó trở thành default của Rails 8 vào cuối 2024 cùng với Solid Cache và Solid Cable. Nó dùng chính relational database của bạn — Postgres, MySQL, hoặc SQLite — làm nơi lưu trữ bền vững và chạy workers như các process riêng poll bảng jobs.

Cả hai đều nói cùng một giao diện Active Job, nên MyJob.perform_later chạy được trên cả hai adapter. Lựa chọn không nằm ở API surface. Nó nằm ở cái gì chạy trên production, cái gì hỏng lúc 3 giờ sáng, và bao nhiêu phần hoá đơn hàng tháng của bạn là hạ tầng bạn không thực sự cần.

Cái rubric tôi thực sự dùng

Quyết định nén lại còn bốn câu hỏi. Tôi chạy theo thứ tự và dừng ở câu đầu tiên cho ra câu trả lời rõ ràng.

Câu hỏiNếu có, nghiêng về SidekiqNếu không, nghiêng về Solid Queue
Bạn đang chạy Redis cho cache/Sidekiq và chi phí migration là có thật?Giữ nguyên
Bạn cần throughput hàng nghìn jobs/giây cho mỗi process?SidekiqSolid Queue ổn
Bạn phụ thuộc vào các tính năng của Sidekiq Pro/Enterprise (batches, unique, rolling restart)?Giữ nguyên
Bạn muốn bớt một stateful service phải vận hành?Solid Queue

Câu đầu tiên là câu hầu hết mọi người bỏ qua. Nếu bạn đã có Sidekiq setup chạy ngon và Redis đã là một managed dependency bạn tin tưởng, chuyển sang Solid Queue là làm migration cho một sở thích thẩm mỹ. Hoá đơn cho một Redis instance nhỏ chỉ vài USD/tháng (~50k-150k VNĐ) trên hầu hết các managed provider. Đó không phải là cái sức ép đủ để buộc bạn phải đổi.

Câu thứ hai là chỗ kiến trúc của Sidekiq trả lại giá trị. Threads trong một process duy nhất, queue state trong bộ nhớ Redis, không có row-level locking đè lên primary database của bạn. Với khối lượng job điển hình của B2B SaaS — webhooks, gửi email, scheduled reports — Solid Queue xử lý nhẹ nhàng không đổ mồ hôi. Với high-frequency event ingestion hoặc background analytics fan-out, Sidekiq vẫn còn dư headroom mà DB-backed runner không có.

Câu thứ ba là cái bẫy với các team đã ở trên Sidekiq Pro. Batches kèm completion callbacks, unique jobs trên toàn cluster, reliability fetcher — những thứ này chưa có bản 1:1 trong Solid Queue. Bạn dựng lại được một số. Bạn sẽ mất một tuần để làm. Tính trước cái tuần đó vào kế hoạch hoặc cứ giữ nguyên.

Câu thứ tư là câu đẩy các dự án mới về phía Solid Queue. Bớt một service phải monitor, bớt một thứ có thể bị cấu hình sai, bớt một dòng trong hoá đơn Render, Fly, hay bất cứ chỗ nào bạn deploy. Với một solo founder ship Rails app đầu tay năm 2026, default kiểu “chỉ có database thôi” thực sự dễ thở hơn.

Những cái bẫy lộ ra sau khi chuyển

Bẫy thứ nhất là coi Solid Queue như Sidekiq với backend khác. Nó không phải vậy. Cơ chế pickup dựa trên polling nghĩa là có một mức sàn latency bằng đúng polling interval của bạn — thường là vài trăm millisecond. Với hầu hết jobs, không ai nhận ra. Với kiểu “gửi SMS đúng cái khoảnh khắc user click nút” thì bạn sẽ thấy, và bạn sẽ muốn giảm polling interval xuống, đổi lại tốn database load.

Bẫy thứ hai là quên rằng bảng jobs của bạn giờ nằm trong primary database. Long-running jobs giữ connection, jobs tự nó làm việc database nặng, và jobs fail trong vòng retry chặt có thể tạo ra contention mà trước đây Redis hấp thụ giùm bạn. Pattern được khuyến nghị là chạy Solid Queue chống lại một database riêng, cũng ổn nhưng lại đẩy ngược một phần độ phức tạp vận hành mà người ta vốn chuyển đi để tránh.

Bẫy thứ ba là chính bản thân việc migration. Chạy song song cả hai adapter trong giai đoạn cutover là khả thi nhưng đòi hỏi kỷ luật về việc queue nào xử lý loại công việc nào. Tôi đã thấy team đổi setting adapter rồi mất cả ngày debug tại sao mấy scheduled jobs đặt từ tuần trước không bao giờ chạy. Drain Sidekiq sạch sẽ, hoặc chấp nhận mất, hoặc viết một rake task one-off để dịch schedule. Đừng “đổi cái rụp” vào ngày thứ Sáu.

Bẫy thứ tư là monitoring. Sidekiq có web UI built-in và hàng chục năm tooling bên thứ ba. Mission Control dashboard của Solid Queue tốt nhưng mới hơn; nếu runbook xử lý sự cố của team bạn đang tham chiếu Sidekiq dashboard bằng URL, mấy URL đó sẽ chết.

Pattern trong thực tế trông như thế nào

Cách đúng để nghĩ về việc này không phải là quyết định một lần mà là một default thay đổi theo từng dự án. Hình hài của quyết định tôi sẽ đưa ra cho một SaaS Rails 8 mới, về mặt khái niệm:

# config/application.rb
config.active_job.queue_adapter = :solid_queue

# config/recurring.yml — thay thế cho sidekiq-cron / sidekiq-scheduler
production:
  cleanup:
    class: CleanupJob
    schedule: every day at 3am

Đó là toàn bộ quyết định hạ tầng. Không Redis cần provision, không sidekiq.yml, không phải đi wire-up dashboard auth riêng. Deploy là bin/jobs start như một process type riêng trong Procfile hoặc render.yaml của bạn.

Hình hài của quyết định tôi sẽ đưa ra cho một Rails app năm tuổi đang dùng Sidekiq Pro:

# Không làm gì cả. Cứ chạy tiếp.
# Xem lại khi tới hạn renew Pro, không sớm hơn.

Hình hài của quyết định tôi sẽ đưa ra cho một app hoàn toàn mới mà tôi biết trong vòng một năm sẽ cần batched fan-out:

Tôi vẫn sẽ bắt đầu trên Solid Queue, vì chi phí chuyển sau này là một ngày công, còn chi phí chạy hạ tầng tôi chưa cần là một năm trả hoá đơn hàng tháng cộng thêm một thứ nữa phải nhớ. Lập luận “có thể bạn sẽ cần” thua lập luận “bạn chưa cần” gần như mọi lần.

Hạ tầng đặt trước thời điểm là cùng một căn bệnh với tối ưu sớm. Cả hai đều tốn tiền thật và chỉ có lãi trong những kịch bản hiếm khi xảy ra.

— Ghi chú cho chính mình

Điểm khái niệm: lựa chọn Sidekiq vs Solid Queue nằm phía sau câu hỏi “tôi đang lạc quan về điều gì và bi quan về điều gì?” Lạc quan về nhu cầu throughput, bi quan về năng lực ops: Sidekiq. Bi quan về nhu cầu throughput, lạc quan về default của Rails: Solid Queue. Cả hai câu trả lời đều bảo vệ được. Không câu nào là phổ quát.

”Xong” trông như thế nào

Bạn biết mình đã chọn đúng khi bạn ngừng nghĩ về nó. Jobs chạy, retries hoạt động đúng, dashboard nói cho bạn biết cái gì fail và vì sao, và on-call rotation không bao giờ phải giải thích cho stakeholder rằng lý do email gửi trễ là vì một stateful service họ thậm chí không biết là tồn tại.

Với Solid Queue cụ thể, “xong” nghĩa là: database chứa jobs (dù chung hay tách) đang được monitor, polling interval đã được tune theo yêu cầu latency của bạn, recurring jobs nằm trong config/recurring.yml thay vì rải rác trong nửa tá cron entry, và bạn có runbook cho tình huống một poison job làm tắc queue. Mission Control được deploy sau lớp auth.

Với Sidekiq, “xong” trông tương tự nhưng có thêm Redis monitoring, có một chiến lược thành văn cho tình huống Redis chết (bạn có chấp nhận mất job không?), và một entry trong lịch nhắc renew cho tier bạn đang trả tiền. Chi phí của “xong” tính theo giờ kỹ sư gần như bằng nhau. Chi phí của “xong” tính theo USD hàng tháng là chỗ hai bên rẽ nhánh.

Khi nào toàn bộ bài này không áp dụng

Nếu bạn đang ở Rails 6 hoặc cũ hơn, phép tính khác — Solid Queue yêu cầu Rails 7.1+ và được tune cho 8. Nếu bạn chạy trên Heroku và chi phí dyno đã bao gồm Redis như một managed addon bạn dính chặt, phần tiết kiệm biến mất. Nếu team bạn không có chút kinh nghiệm vận hành Postgres nào và lại có một đội ngũ Redis dày dặn, chuyển sang database-backed runner là dời failure surface về phía bạn hiểu ít hơn.

Và nếu background work của bạn chỉ là một cron đêm gửi PDF, bạn không cần cái nào trong hai cái này. Bạn cần whenever và một rake task. Tôi đã chứng kiến người ta tranh luận Sidekiq vs Solid Queue cho một app mà tổng khối lượng background là bốn jobs một ngày. Chọn cái nào cũng được. Đi tiếp đi.

Luận điểm có thể phản biện

Đây là cái lằn ranh tôi sẽ bảo vệ: với một Rails 8 app ship phiên bản đầu tiên năm 2026, chưa có Redis dependency và workload background SaaS điển hình (dưới vài trăm jobs/phút lúc peak), chọn Sidekiq thay vì Solid Queue sẽ tốn nhiều hơn về chi phí hạ tầng tích luỹ và overhead vận hành trong hai năm đầu so với số giờ kỹ sư cần để migrate sang Solid Queue sau này nếu bạn vượt quá khả năng của nó. Nếu ai đó chạy phép so sánh này một cách trung thực và tìm ra kết quả ngược lại, tôi muốn xem con số.