Server

504 Gateway Timeout — Nguyên nhân và cách khắc phục

Cập nhật 2026-08-30Đọc ~9 phút

504 Gateway Timeout nghĩa là máy chủ phía trước — thường là Nginx hoặc một load balancer — đã chuyển tiếp yêu cầu của bạn tới backend, rồi ngồi chờ, và cuối cùng bỏ cuộc. Backend không từ chối, không sập, nó chỉ đơn giản chưa trả lời kịp.

Phân biệt được điều này với 502 giúp tiết kiệm rất nhiều thời gian. 502 nghĩa là backend trả về thứ gì đó vô nghĩa hoặc đã chết; 504 nghĩa là nó vẫn đang chạy, vẫn đang làm việc, chỉ là chậm hơn giới hạn kiên nhẫn được cấu hình sẵn. Gần như mọi lần sửa 504 đều quy về một trong hai việc: làm cho công việc nhanh lên, hoặc nâng giới hạn chờ — và thứ tự đó không nên đảo ngược.

504 khác 502, 503 và 408 ra sao

Bốn mã này đều xuất hiện khi có gì đó sai giữa proxy và ứng dụng, nhưng mỗi mã chỉ về một chỗ khác nhau.

Chuyện gì đã xảy raNhìn vào đâu trước
504 Gateway TimeoutBackend còn sống nhưng trả lời quá chậmTruy vấn chậm, API bên ngoài, tiến trình chạy dài
502 Bad GatewayBackend chết hoặc trả về phản hồi hỏngLog crash của PHP-FPM, Node, Gunicorn
503 Service UnavailableMáy chủ chủ động từ chối nhận thêm việcHàng đợi đầy, bảo trì, giới hạn tốc độ
408 Request TimeoutMáy khách gửi yêu cầu quá chậmMạng phía người dùng, upload lớn
💡 Nếu bạn thấy 502 và 504 xen kẽ nhau trên cùng một trang, thường là backend đang chậm dần rồi bị process manager giết vì quá giờ — hãy sửa phần chậm, cả hai mã sẽ cùng biến mất.

Con số timeout nào đang thực sự hết hạn

Đây là phần khiến 504 khó chịu hơn cần thiết: một yêu cầu đi qua nhiều lớp, mỗi lớp có đồng hồ đếm ngược riêng, và lớp nào hết trước sẽ quyết định thông báo bạn nhìn thấy. Nâng nhầm con số thì chẳng thay đổi được gì.

LớpTham số thường gặpMặc định điển hình
Nginx → backendproxy_read_timeout60 giây
Nginx → PHP-FPMfastcgi_read_timeout60 giây
PHPmax_execution_time30 giây
PHP-FPMrequest_terminate_timeoutthường tắt
Cloudflare (gói miễn phí)timeout cố định100 giây — không đổi được
💡 Nếu bạn dùng Cloudflare gói miễn phí, giới hạn 100 giây là trần cứng. Không cấu hình nào trên máy chủ vượt qua được nó — yêu cầu chạy lâu hơn phải chuyển sang chạy nền, không có cách khác.

Nguyên nhân thường gặp, phổ biến nhất trước

  • Truy vấn cơ sở dữ liệu chậm. Nguyên nhân số một, gần như luôn là một truy vấn thiếu index quét toàn bộ bảng khi dữ liệu đã lớn lên.
  • Gọi API bên ngoài không đặt timeout. Ứng dụng của bạn chờ một dịch vụ bên thứ ba đang chậm, và vì không giới hạn thời gian chờ nên nó chờ mãi.
  • Tác vụ nặng chạy ngay trong yêu cầu HTTP. Xuất báo cáo, gửi hàng loạt email, xử lý ảnh — những việc này thuộc về hàng đợi nền chứ không phải chu kỳ yêu cầu.
  • Hết worker. Mọi tiến trình PHP-FPM hoặc Node đều đang bận với các yêu cầu chậm, nên yêu cầu mới xếp hàng cho tới khi hết giờ mà chưa được xử lý.
  • Cron chạy đè lên nhau. wp-cron trên site nhiều lượt truy cập kích hoạt theo mỗi lượt xem, chồng chất lên nhau và ăn hết worker.
  • Máy chủ hết RAM và bắt đầu swap. Mọi thứ vẫn hoạt động, chỉ là chậm gấp hàng chục lần, và timeout xuất hiện trên toàn bộ website.
  • Plugin hoặc thư viện thao tác mạng khi tải trang. Kiểm tra bản cập nhật, xác thực giấy phép, tải font từ xa — mỗi thứ thêm vài giây vào thời gian phản hồi.

Kiểm tra theo thứ tự này

  • Xác định lỗi xảy ra ở mọi trang hay chỉ vài trang. Toàn site chậm thường là tài nguyên máy chủ; một trang cụ thể chậm gần như luôn là một truy vấn hoặc một lệnh gọi bên ngoài trên đúng trang đó.
  • Đo thời gian phản hồi thật bằng "curl -o /dev/null -s -w '%{time_total}\n' https://trangcuaban.com/". Con số này cho biết bạn đang ở sát ngưỡng hay vượt xa nó.
  • Bật slow query log của MySQL với ngưỡng 1 giây rồi để chạy vài phút. Đây là bước cho kết quả nhanh nhất trong toàn bộ danh sách.
  • Xem error log của Nginx. Dòng "upstream timed out" ghi rõ backend nào và endpoint nào đã hết giờ.
  • Kiểm tra RAM và swap bằng "free -m". Nếu swap đang được dùng nhiều, hãy xử lý bộ nhớ trước — mọi thứ khác chỉ là chữa triệu chứng.
  • Đếm số worker đang bận so với tổng số. PHP-FPM có trang status; nếu luôn chạm trần pm.max_children, hàng đợi mới là vấn đề chứ không phải bản thân timeout.
  • Tạm tắt các thành phần gọi mạng bên ngoài. Nếu 504 biến mất, bạn đã tìm được thủ phạm và có thể đặt timeout ngắn cho lệnh gọi đó.
  • Chỉ nâng timeout sau khi đã biết chính xác cái gì chậm, và nâng như một biện pháp tạm thời có chủ đích, không phải như cách sửa.
💡 Nâng proxy_read_timeout lên 300 giây làm 504 biến mất nhưng thay nó bằng một trang tải mất 4 phút. Khách sẽ rời đi từ lâu trước khi trang xong, nên chỉ số duy nhất thay đổi là thông báo lỗi.

Cách sửa đúng gốc

Khi đã biết chỗ nào chậm, cách xử lý gần như luôn rơi vào một trong ba nhóm dưới đây.

Thêm index cho truy vấn chậm. Một cột được lọc thường xuyên mà không có index sẽ khiến cơ sở dữ liệu đọc toàn bộ bảng ở mỗi yêu cầu. Chạy EXPLAIN trên truy vấn chậm nhất trong log; nếu thấy quét toàn bảng, bạn đã có việc cần làm và thường mất chưa tới một phút.

Đưa việc chạy lâu ra khỏi chu kỳ yêu cầu. Xuất file, gửi email, tạo thumbnail và đồng bộ dữ liệu nên chạy trong hàng đợi nền, còn yêu cầu HTTP chỉ trả về ngay lập tức rằng công việc đã được nhận. Đây là thay đổi tốn công nhất nhưng cũng là thay đổi loại bỏ vĩnh viễn cả một nhóm lỗi 504.

Đặt timeout cho mọi lệnh gọi ra ngoài. Bất kỳ yêu cầu nào tới dịch vụ bên thứ ba đều phải có giới hạn thời gian vài giây kèm cách xử lý khi thất bại. Không có nó, một API chậm ở đầu kia thế giới sẽ trực tiếp trở thành trang lỗi của bạn.

Nếu tất cả đều đã hợp lý mà máy chủ vẫn không đủ sức, lúc đó vấn đề mới thực sự là tài nguyên. CPU luôn cao, RAM luôn cạn và swap hoạt động liên tục là dấu hiệu thật cho việc nâng cấp — khác hẳn với việc nâng cấp chỉ vì thấy 504.

Cần tài nguyên đủ để không phải chạy đua với timeout?

Cloud VPS NVMe với quyền root đầy đủ — tự chỉnh timeout, slow query log và số worker theo ý mình. Từ ฿150/tháng.

Câu hỏi thường gặp

Tôi đã nâng timeout mà vẫn bị 504. Vì sao?

Vì bạn nâng nhầm lớp. Một yêu cầu đi qua Nginx, rồi PHP-FPM hoặc application server, rồi tới cơ sở dữ liệu, và mỗi lớp có timeout riêng — lớp nào ngắn nhất sẽ thắng. Nếu website chạy sau Cloudflare gói miễn phí, còn có trần cứng 100 giây mà không cấu hình nào trên máy chủ vượt được.

504 có ảnh hưởng SEO không?

Có, nếu kéo dài. Googlebot gặp 504 sẽ thử lại sau, và vài lần lẻ tẻ hầu như không gây hại gì. Nhưng timeout liên tục nhiều ngày sẽ làm giảm tốc độ thu thập và cuối cùng khiến trang rơi khỏi chỉ mục. Báo cáo Crawl stats trong Search Console cho biết Googlebot thực sự gặp bao nhiêu lỗi.

Vì sao 504 chỉ xảy ra vào giờ cao điểm?

Vì bạn đang cạn worker chứ không phải cạn thời gian. Khi mọi tiến trình đều bận, yêu cầu mới phải xếp hàng và đồng hồ timeout bắt đầu chạy trước cả khi có ai xử lý chúng. Hãy tìm truy vấn chậm giữ worker quá lâu, thay vì tăng số worker lên rồi lại cạn RAM.

Trang admin WordPress bị 504 nhưng phần công khai vẫn ổn. Vì sao?

Vì trang admin không được cache và chạy nhiều truy vấn hơn hẳn. Nguyên nhân phổ biến nhất là bảng wp_options phình to vì transient hết hạn, hoặc plugin kiểm tra cập nhật khi tải trang. Dọn transient cũ và tắt plugin lần lượt để tìm thủ phạm.