Lần deploy kết thúc đúng lúc đèn văn phòng dịu xuống vào cuối ngày. Không có server để SSH vào, không có process manager để restart, cũng không có tên máy nào cần nhớ. Một function nhỏ vừa được push lên, một queue đang chờ message, một event từ object storage sẽ đánh thức code khi file mới xuất hiện. Màn hình nhìn rất gọn, gần như gọn đến mức hơi đáng nghi. Serverless thường bắt đầu bằng cảm giác như vậy.
Serverless không có nghĩa là không còn server. Nó là quyết định không trực tiếp sở hữu một số trách nhiệm vận hành server nữa. Vẫn có ai đó chạy máy, patch runtime, cấp capacity, thay phần hỏng, và route traffic. Điểm khác là cloud platform giấu phần lớn công việc đó sau managed service và event-driven execution. Team của bạn viết code gần hơn với business event: một image được upload, một payment webhook đến, một message vào queue, một lịch chạy lúc nửa đêm.
Lợi ích dễ thấy nhất là sự tập trung. Một team nhỏ có thể xây một workflow hữu ích mà không phải duy trì cluster, chỉnh autoscaling policy, hay giữ idle capacity nóng cả ngày. Một function có thể scale từ số không lên nhiều invocation khi traffic đến, rồi quay lại trạng thái yên tĩnh. Với workload không đều, internal tool, background job, prototype, hoặc integration dựa nhiều trên event, đây có thể là một trade-off rất hợp lý.
Serverless cũng tạo ra một áp lực kiến trúc khá tốt. Vì function thường nhỏ và đi theo event, nó buộc mình đặt tên boundary rõ hơn. Một function validate webhook. Một function transform document. Một function gửi notification. Khi design khỏe, hệ thống bắt đầu giống một tập trách nhiệm nhỏ được nối với nhau bằng event bền vững. Điều này có thể làm việc thay đổi dễ hơn, nhất là khi mỗi phần chỉ có một lý do để tồn tại.
Nhưng sự thật đầu tiên là serverless không xóa architecture. Nó chuyển architecture sang service boundary, event contract, retry, permission và observability. Một API chậm trong monolith có thể dễ trace trong một process. Một workflow serverless chậm có thể đi qua API gateway, function, queue, function khác, database và notification service. Nếu team không đầu tư vào correlation ID, structured log, metric và alarm rõ ràng, hệ thống chỉ yên tĩnh từ bên ngoài. Bên trong, debug có thể giống lần theo dấu chân trong sương.
Sự thật thứ hai là limit luôn có tiếng nói. Function có execution time limit, memory limit, payload limit, concurrency limit, package size limit và constraint của runtime. Những giới hạn này không phải lúc nào cũng xấu. Chúng ép mình có kỷ luật. Nhưng chúng đau khi workload cần chạy lâu, giữ state nhiều, giao tiếp quá chặt, hoặc cần custom sâu. Một video processing pipeline có thể rất hợp nếu được chia thành từng bước. Một engine cần low latency ổn định, một model lớn nằm trong memory, hoặc một collaborative editor nhiều websocket có thể sẽ đánh nhau với platform liên tục.
Cold start là một cái giá khác cần nói thật. Nhiều workload chấp nhận được độ trễ lúc function thức dậy. Một số thì không. Nếu một endpoint người dùng gọi đôi khi phải chờ vì platform chuẩn bị runtime, trải nghiệm sẽ thiếu nhất quán. Có cách giảm: provisioned concurrency, package nhỏ hơn, runtime nhẹ hơn, dependency gọn hơn. Nhưng latency nên được xem là câu hỏi sản phẩm, không chỉ là chi tiết infrastructure. Một job tạo invoice chạy nền có thể chờ. Một login request thì khó khoan dung hơn.
Cost cũng có hai mặt. Serverless có thể rẻ hơn vì bạn trả tiền cho usage thật thay vì máy rảnh. Nó cũng có thể làm bạn bất ngờ vì mỗi invocation, message, read, write, storage operation, log line và retry đều có giá. Một bug làm queue chạy vòng lặp có thể vừa thành incident vừa thành hóa đơn. Một quyết định log quá nhiều có thể vô hại ở development nhưng đắt ở production. Câu hỏi đúng không chỉ là serverless có rẻ không. Câu hỏi tốt hơn là cost model có khớp với traffic shape không, và team có nhìn thấy biến động cost đủ sớm không.
Vendor lock-in cũng xứng đáng có một cuộc nói chuyện bình tĩnh. Nó có thật, nhưng không tự động là lý do để né serverless. Mọi abstraction hữu ích đều tạo dependency ở mức nào đó. Relational database, queue, search engine, framework và cloud provider đều định hình hệ thống. Câu hỏi thực tế là portability quan trọng ở đâu. Nếu product phụ thuộc sâu vào event model, IAM, queue behavior và deployment pipeline của một cloud, migration sẽ đắt. Điều đó vẫn có thể chấp nhận được nếu managed platform tiết kiệm nhiều năm vận hành.
Một design serverless khỏe thường bắt đầu nhỏ. Chọn một workflow có event rõ và nhu cầu latency vừa phải. Giữ responsibility của function hẹp. Làm event explicit và versioned. Thêm idempotency trước khi retry thành vấn đề. Đặt tracing và dashboard trước incident thật đầu tiên. Làm local development đủ giống để bắt lỗi cơ bản, nhưng đừng tự lừa rằng local simulation giống hệt cloud. Managed platform là một phần của hệ thống, nên staging cũng cần chạy qua managed platform.
Serverless hữu ích nhất khi team chấp nhận constraint của platform để đổi lấy tốc độ, elasticity và bề mặt vận hành nhỏ hơn. Nó ít hữu ích khi team cần kiểm soát sâu, low latency rất ổn định, long-lived state, hoặc portability quan trọng hơn tất cả. Ở giữa hai cực đó, nhiều hệ thống thật sẽ pha trộn: serverless cho event workflow, container cho service chạy lâu, managed database cho persistence, và vài scheduled job đơn giản nơi một function là vừa đủ.
Sự thật lặng lẽ là serverless không phải phép màu và cũng không phải cái bẫy. Nó là một cuộc trao đổi. Bạn giao bớt một phần control hạ tầng, đổi lại một platform có thể gánh nhiều việc vận hành không tạo khác biệt cho sản phẩm. Cuộc trao đổi đó tốt khi bạn hiểu mình vẫn sở hữu gì: contract, failure mode, data flow, security, observability, latency và cost. Lần tới khi một team nói feature này nên làm serverless, câu trả lời hữu ích không phải là có hay không. Hãy hỏi: mình đang giao đi trách nhiệm nào, và trách nhiệm nào trở nên quan trọng hơn vì quyết định đó?