Nguyen Le PhongNguyen Le Phong

Lần đầu tiên tôi làm hỏng production

Một bài viết chậm lại về lần đầu một thay đổi nhỏ gây ảnh hưởng thật trên production: khoảng lặng sau alert, rollback, buổi incident review không dễ chịu, và bài học rằng kỹ thuật tốt được xây bằng thói quen, guardrail và ownership chung hơn là panic cá nhân.

Lần đầu tiên tôi làm hỏng production, văn phòng yên tĩnh theo một cách rất bình thường. Vài người vẫn đứng gần máy pha cà phê, ai đó để quên áo khoác trên lưng ghế, còn trình duyệt của tôi vẫn hiện dấu check xanh từ deployment pipeline. Không có gì trong căn phòng trông có vẻ kịch tính. Rồi tin nhắn bắt đầu tới nhanh hơn bình thường, ban đầu là vài câu hỏi nhỏ, sau đó là screenshot, rồi tới câu mà developer nào cũng nhận ra: production đang có vấn đề.

Đó không phải một lỗi anh hùng. Cũng không phải một edge case thông minh chỉ xuất hiện dưới lượng traffic bất khả thi. Nó là một thay đổi nhỏ, được review khá nhanh, merge với sự tự tin hợp lý, rồi release vào một hệ thống có nhiều assumption hơn tôi hiểu lúc đó. Một giá trị trông có vẻ optional ở một chỗ lại âm thầm là bắt buộc ở chỗ khác. Một trang bắt đầu fail. Rồi một workflow khác trở nên không ổn định. Ảnh hưởng không làm cả công ty sụp đổ, nhưng đủ thật để mọi người dừng việc đang làm và cùng nhìn vào mấy dashboard.

Phản ứng đầu tiên của tôi không phải sự khôn ngoan. Nó là mặt nóng lên, bụng thắt lại, và một mong muốn rất lạ rằng vấn đề này bằng cách nào đó thuộc về một commit khác. Tôi muốn sửa ngay lập tức vì mỗi giây trôi qua giống như một thước đo công khai về năng lực của mình. Đó là một trong những phần khó nhất của một production incident đầu tiên: bài toán kỹ thuật nằm ngay trước mặt, nhưng một bài toán khác cũng đang diễn ra bên trong bạn. Bạn phải debug hệ thống trong khi đồng thời quản lý cái thôi thúc bảo vệ hình ảnh của chính mình.

Một người có nhiều kinh nghiệm hơn hỏi một câu rất đơn giản: mình rollback an toàn được không? Câu hỏi đó làm căn phòng có hình dạng trở lại. Chúng tôi ngừng đuổi theo năm giả thuyết cùng lúc và tập trung vào việc giảm thiệt hại. Rollback không có gì hào nhoáng. Nó là một hành động rất bình thường, rất thực tế, đưa hệ thống quay về vùng đất đã biết. Alert chậm lại. Tin nhắn từ support bớt gấp. Căn phòng không ăn mừng. Nó chỉ thở ra.

Sau đó mới tới phần khó chịu: đọc lại code mà không còn hy vọng rằng code sẽ bênh vực mình. Bug trở nên rõ ràng khi chúng tôi nhìn nó bình tĩnh hơn. Tôi đã đổi behavior ở một layer và bỏ sót contract mà nó có với layer khác. Test có cover happy path, nhưng không cover shape dữ liệu cũ. Review không tệ, nhưng quá hẹp. Deployment pipeline xanh, nhưng pipeline chỉ biết những gì chúng tôi đã dạy nó biết. Những sự thật đó không xóa trách nhiệm của tôi. Chúng chỉ làm trách nhiệm đó hữu ích hơn sự xấu hổ.

Bài học tôi mang theo từ ngày đó không chỉ là, hãy cẩn thận hơn. Cẩn thận là cần, nhưng nó quá mong manh nếu chỉ dựa vào nỗi sợ. Một engineer đang sợ có thể kiểm tra rất kỹ một thay đổi hôm nay, rồi vẫn bỏ sót một thay đổi khác ngày mai. Bài học tốt hơn là production safety đến từ các thói quen và guardrail giúp sự cẩn thận dễ lặp lại hơn: release nhỏ hơn, contract rõ hơn, migration plan, test có dữ liệu cũ, observability chỉ được đường fail, và một văn hóa team nơi câu tôi chưa chắc rẻ hơn việc giả vờ tự tin.

Incident đó cũng đổi cách tôi đọc code review. Trước đây, tôi chủ yếu nhìn xem code có chạy không. Sau đó, tôi bắt đầu hỏi những câu yên hơn. Thay đổi này đang giả định điều gì? Trạng thái cũ nào vẫn còn có thể tồn tại? Nếu chuyện này sai, mình sẽ biết bằng cách nào? Có tắt được không? Có rollback được mà không làm dữ liệu tệ hơn không? Những câu hỏi này không kịch tính. Chúng không làm một pull request trông ấn tượng hơn. Nhưng đó là những câu hỏi bình thường giúp một hệ thống bớt phụ thuộc vào may mắn.

Tôi cũng học thêm một điều về sự tử tế trong engineering. Một buổi review không đổ lỗi không có nghĩa là không ai chịu trách nhiệm. Nó có nghĩa là team quan tâm nhiều hơn đến việc tìm con đường đã cho phép lỗi xảy ra, thay vì biến một người thành toàn bộ lời giải thích. Đổ lỗi đôi khi tạo cảm giác đã tay vì nó đơn giản. Nhưng một production incident thường là một chuỗi những cho phép nhỏ: một test thiếu, một contract mơ hồ, một assumption vội, một dashboard không ai xem, một thói quen release vẫn ổn cho tới khi không còn ổn. Khi team học được chuỗi đó, mọi người đều an toàn hơn một chút.

Một thời gian, tôi nhớ ngày đó chủ yếu như một sự xấu hổ. Về sau, tôi bắt đầu nhìn nó như một ngưỡng nghề nghiệp rất lặng. Không phải vì làm hỏng production là một huy hiệu, và cũng không phải vì mọi thất bại tự động có giá trị. Nó chỉ có giá trị vì có người giúp biến nó thành thực hành tốt hơn. Release sau nhỏ hơn. Thay đổi rủi ro sau có ghi chú rollback. Review sau có thêm một câu hỏi về dữ liệu cũ. Không có gì biến đổi sau một đêm. Hệ thống an toàn hơn bằng những lần lặp nhỏ mà từ bên ngoài rất dễ không thấy.

Nếu bạn còn sớm trong nghề và vừa gây ra một bug, bỏ sót một case, hoặc nhìn thay đổi của mình cư xử tệ trước mặt user, tôi mong bạn đừng biến khoảnh khắc đó thành một bản án riêng về con người mình. Hãy nhận trách nhiệm, sửa điều có thể sửa, rồi hỏi hệ thống cần gì để người tiếp theo có một con đường dễ hơn. Kinh nghiệm được xây như vậy: không phải bằng cách không bao giờ chạm vào thứ mong manh, mà bằng cách học chạm vào những thứ mong manh với nhiều context hơn, nhiều khiêm tốn hơn, và nhiều hỗ trợ hơn.

Tôi vẫn không thích incident. Tôi nghĩ cũng không ai nên thích. Nhưng tôi biết ơn điều incident đầu tiên dạy mình về khác biệt giữa panic và ownership. Panic nói, làm ơn dừng chuyện này lại để mình hết cảm giác bị phơi ra. Ownership nói, giảm thiệt hại, hiểu con đường, cải thiện guardrail, và để bài học trở thành một phần trong cách team làm việc. Nếu bạn cũng có câu chuyện production đầu tiên của riêng mình, tôi rất muốn biết điều gì còn ở lại với bạn sau khi alert đã im.

Bạn thấy bài viết thế nào?