Chạy ứng dụng như một hoặc nhiều process stateless
- Theo Twelve-Factor, ứng dụng nên được thực thi dưới dạng một hoặc nhiều process stateless, share-nothing; mọi dữ liệu cần tồn tại lâu dài phải được đưa vào một stateful backing service, thường là database.
- Bộ nhớ và filesystem của process chỉ nên được xem như cache ngắn hạn cho một transaction/job, và ứng dụng không được giả định rằng dữ liệu còn nằm đó ở request hoặc job kế tiếp.
- Twelve-Factor nói rất rõ rằng sticky sessions là vi phạm nguyên tắc này; session state nên nằm trong một datastore có expiration như Memcached hoặc Redis, thay vì nằm trong RAM của một app process cụ thể.
- Trong thực tế hiện đại, Heroku vận hành app trên các dyno có ephemeral filesystem và tự động thay dyno ít nhất mỗi ngày; còn Kubernetes xem Deployment là lựa chọn phù hợp cho workload stateless, trong khi StatefulSet dành cho workload cần danh tính và lưu trữ bền vững.
1) Mở bài: vì sao factor này đụng đúng “nỗi đau” production?
Một hệ thống thường bắt đầu rất ngây thơ: app web chỉ chạy một instance, session để trong RAM cho nhanh, file upload lưu tạm vào disk local, cache render kết quả luôn trong process. Mọi thứ có thể vẫn “ổn” khi chỉ có một máy. Nhưng đến lúc scale lên nhiều instance, hoặc chỉ đơn giản là app restart, deploy lại, hay bị scheduler dời sang máy khác, những giả định đó bắt đầu vỡ hàng loạt. Twelve-Factor đưa ra Factor VI để cắt đứt kiểu phụ thuộc ngầm vào bộ nhớ và filesystem cục bộ của process.
2) Định nghĩa gốc của Factor VI
Tên chính thức của factor này là:
“Processes — Execute the app as one or more stateless processes.”
Tài liệu gốc nói rất ngắn nhưng rất mạnh: process của Twelve-Factor phải stateless và share-nothing. Nếu dữ liệu cần được giữ lại sau khi process kết thúc hoặc sau một request/job hoàn tất, dữ liệu đó phải nằm trong một backing service có state, thường là database.
Nói đơn giản cho người mới:
Process của app chỉ nên là “cục máy xử lý việc”. Nó nhận input, xử lý, trả output. Nó không nên là nơi giữ trạng thái quan trọng của ứng dụng qua thời gian.
3) “Stateless” ở đây nghĩa là gì?
“Stateless” không có nghĩa là app của bạn không có dữ liệu, cũng không có nghĩa là hệ thống của bạn không có state. Twelve-Factor không hề phủ nhận chuyện hệ thống cần database, queue, object storage hay cache. Điều nó muốn nói là: state quan trọng không nên bị giam trong chính process của app. Process chỉ là nơi xử lý tạm thời; state bền vững phải được đưa ra backing services.
Ví dụ:
- đơn hàng vẫn phải lưu trong database,
- session đăng nhập có thể nằm ở Redis,
- file người dùng upload nên nằm ở object storage hoặc dịch vụ lưu trữ phù hợp,
- còn process web/worker thì có thể chết đi, được thay thế, hoặc scale ra nhiều bản mà không làm mất logic nghiệp vụ.
4) “Share-nothing” nghĩa là gì?
“Share-nothing” ở đây nghĩa là từng process không nên phụ thuộc vào việc chia sẻ memory hoặc local disk với process khác như một phần bình thường của logic ứng dụng. Twelve-Factor nhấn mạnh rằng request hoặc job kế tiếp có khả năng rất cao sẽ được phục vụ bởi một process khác, nên app không được kỳ vọng dữ liệu cache trong RAM hoặc trên disk local của process hiện tại sẽ còn đó cho lần sau.
Đây là ý cực kỳ quan trọng khi scale-out. Một khi bạn có nhiều process cùng loại chạy song song, khái niệm “request sau chắc vẫn vào đúng con app này” trở nên rất mong manh. Twelve-Factor coi việc dựa vào giả định đó là thiết kế sai ngay từ đầu.
5) Bộ nhớ và filesystem local có được dùng không?
Có, nhưng với giới hạn rất rõ. Tài liệu gốc nói memory space hoặc filesystem của process có thể dùng như cache ngắn hạn cho một transaction đơn lẻ. Ví dụ, tải một file lớn về, xử lý nó, rồi ghi kết quả vào database là hoàn toàn ổn. Điều không được làm là giả định dữ liệu tạm đó sẽ còn tồn tại ở request hoặc job sau.
Tài liệu gốc còn nhấn mạnh: kể cả khi bạn chỉ đang chạy một process, việc restart do deploy mới, thay đổi config, hoặc execution environment dời process sang vị trí vật lý khác vẫn thường làm mất toàn bộ state cục bộ trong memory và filesystem.
6) Sticky sessions vì sao lại bị xem là sai?
Đây là một trong những ví dụ kinh điển nhất của Factor VI. Tài liệu gốc nói rõ: một số hệ thống web dùng sticky sessions, tức là lưu session state của user trong memory của một app process và kỳ vọng những request sau của cùng user sẽ luôn được định tuyến lại đúng process đó. Twelve-Factor coi đây là vi phạm và nói thẳng rằng không nên dùng hay dựa vào sticky sessions. Session state là ứng viên tốt để đưa vào datastore có time-expiration như Memcached hoặc Redis.
Lý do rất dễ hiểu: sticky sessions biến một app process thành “ngăn kéo bí mật” chứa trạng thái người dùng. Một khi process đó crash, bị thay, hoặc traffic bị chuyển hướng sang process khác, bạn bắt đầu thấy các lỗi khó chịu như mất session, đăng nhập lại bất ngờ, hoặc hành vi lúc được lúc không.
7) Ví dụ đời thường cực dễ hiểu
Hãy tưởng tượng mỗi process là một nhân viên phục vụ trong quán trà sữa. Một nhân viên tốt có thể nhận order, pha đồ, giao ly, rồi ghi thông tin cần lưu vào hệ thống trung tâm. Người đó không nên giữ toàn bộ lịch sử đơn hàng trong đầu và bắt quán phải đảm bảo “khách A lần sau nhất định quay lại đúng nhân viên này”. Nếu quán vận hành như vậy, chỉ cần nhân viên nghỉ ca là hệ thống rối ngay. Đây chính là tinh thần của stateless process.
8) Ví dụ xuyên suốt với ứng dụng mẫu TaskFlow
Ta tiếp tục dùng ứng dụng mẫu TaskFlow, một SaaS quản lý công việc cho đội nhóm. TaskFlow có các process như:
webđể xử lý HTTP request,workerđể chạy background jobs,schedulerđể kích hoạt việc định kỳ.
Cách làm đúng
webđọc dữ liệu task từ PostgreSQL.- session hoặc token state ngắn hạn nằm ở Redis hay cơ chế token phù hợp.
- file đính kèm lưu trong object storage.
workerlấy job từ queue rồi xử lý, xong thì ghi kết quả về backing service.- nếu một
webprocess chết, load balancer có thể đưa request sang process khác mà không làm mất logic ứng dụng.
Cách làm sai
- session user nằm trong RAM của từng
webprocess, - file upload nằm trên disk local của container/app instance,
- worker ghi checkpoint dở dang ra thư mục local rồi hy vọng lần chạy sau vẫn được đúng instance đó đọc lại,
- một cron process lưu “trạng thái đã chạy đến đâu” trong local file thay vì backing service.
Những cách làm sai này có thể vẫn chạy được trong môi trường nhỏ, nhưng càng deploy trên nền tảng hiện đại với restart, reschedule và scale-out thường xuyên, chúng càng dễ gãy. Twelve-Factor được tạo ra chính để giúp app tránh các bẫy kiểu đó.
9) Case thực tế đã được xác minh
Heroku: dyno có filesystem tạm thời
Tài liệu chính thức của Heroku nói rõ rằng dyno — các Linux container chạy code của bạn — có ephemeral filesystem. Heroku còn cho biết dyno được tự động thay ít nhất mỗi ngày, và mỗi lần như vậy, mọi dữ liệu ứng dụng đã ghi vào local filesystem đều mất. Tài liệu này khuyên app phải dùng database hoặc object storage thay vì local filesystem cho dữ liệu cần tồn tại lâu dài. Đây là một ví dụ rất thực tế của việc platform buộc ứng dụng phải tôn trọng tính stateless của process.
Kubernetes: Deployment cho stateless, StatefulSet cho stateful
Tài liệu chính thức của Kubernetes mô tả Deployment là lựa chọn phù hợp để quản lý stateless application workload, nơi các Pod là interchangeable và có thể thay thế khi cần. Ngược lại, StatefulSet được dùng cho ứng dụng cần sticky identity, persistent storage hoặc stable network identity. Đây là một minh họa rất rõ cho cách cloud-native platform hiện đại phân biệt giữa process stateless và workload có state bền vững.
Điểm hay ở đây là: Twelve-Factor không nói “mọi thứ trong hệ thống phải stateless”. Nó nói process của app nên stateless. Kubernetes cũng phản ánh đúng tinh thần đó khi tách Deployment và StatefulSet cho hai nhu cầu khác nhau.
10) Junior thường hiểu sai ở đâu?
Hiểu sai 1: “Stateless là không được cache gì cả”
Không đúng. Tài liệu gốc cho phép dùng memory hoặc filesystem như cache rất ngắn hạn cho một transaction. Điều bị cấm là dựa vào cache đó cho request hoặc job tương lai như thể nó là state bền vững.
Hiểu sai 2: “Nếu chỉ có một instance thì lưu local cũng được”
Twelve-Factor nói rõ ngay cả với một process duy nhất, restart do deploy, đổi config hoặc relocation của execution environment vẫn thường xóa local state. Một thiết kế đúng không nên phụ thuộc vào “hiện tại mới có một instance nên cứ để tạm trong máy”.
Hiểu sai 3: “Sticky sessions là tối ưu hợp lý”
Theo tài liệu gốc, sticky sessions là vi phạm Twelve-Factor. Đây không phải kiểu “không khuyến khích lắm”, mà là thứ không nên dùng hoặc dựa vào. Session state nên đi vào backing service phù hợp như Redis hoặc Memcached.
Hiểu sai 4: “Process stateless thì hệ thống không thể có database state”
Sai. Twelve-Factor yêu cầu state quan trọng phải ở backing service, không phải biến mất hoàn toàn. Database, cache, object storage và các backing services khác vẫn là nơi hệ thống giữ trạng thái dài hạn.
11) Làm sai thì hậu quả gì?
- Scale-out khó hoặc scale ra là lỗi, vì request tiếp theo có thể đi vào process khác không còn giữ state cũ.
- Deploy hoặc restart gây mất dữ liệu cục bộ, đặc biệt khi platform dùng filesystem tạm thời như Heroku dynos.
- Khó tận dụng orchestration hiện đại, vì các nền tảng như Kubernetes giả định Pod có thể bị thay, còn Deployment đặc biệt phù hợp cho stateless workload.
- Session và workflow trở nên mong manh, nhất là khi đang phụ thuộc vào sticky sessions hoặc local files cho trạng thái vận hành.
12) Áp dụng đúng trong team như thế nào?
Bước 1: Xác định state nào là “thật sự cần tồn tại”
Task data, user state, uploaded files, workflow progress, idempotency keys, rate-limit counters — những thứ này cần được xác định rõ cái nào là state nghiệp vụ hoặc state vận hành quan trọng. Nếu nó cần sống sót qua restart hoặc cần thấy được từ nhiều process, nó không nên nằm trong RAM hay local disk của một process.
Bước 2: Đưa state đó vào backing services phù hợp
- dữ liệu nghiệp vụ vào database,
- session hoặc ephemeral shared state vào Redis/Memcached nếu phù hợp,
- file vào object storage hoặc dịch vụ lưu trữ bền vững,
- checkpoint job vào database hoặc store có durability phù hợp.
Bước 3: Thiết kế process như worker có thể thay thế
Mỗi web process, worker process hay scheduler process nên có thể bị kill rồi được thay thế bằng process khác mà hệ thống vẫn đúng. Điều này đi rất tự nhiên với phần Concurrency của Twelve-Factor, nơi process được xem là first-class citizen và mỗi loại công việc có thể được gán cho một process type riêng.
Bước 4: Không dùng sticky sessions
Nếu app web đang dựa vào sticky sessions, đó gần như là tín hiệu đỏ của Factor VI. Hãy chuyển session state sang backing service hoặc chuyển sang cơ chế token/stateless auth phù hợp với bài toán của bạn. Twelve-Factor nêu rất rõ đây là hướng đúng.
Bước 5: Kiểm tra local filesystem usage
Bất kỳ chỗ nào đang ghi file “để dùng lại sau” trên local disk của app instance đều nên bị đặt câu hỏi. Heroku docs là một ví dụ rất trực diện: dữ liệu trên local filesystem của dyno sẽ mất khi dyno bị thay.
13) Diễn giải trong bối cảnh hiện đại
Blog chính thức năm 2025 của Twelve-Factor nói rằng containers, Kubernetes và cloud-native architectures đã mang đến nhiều độ phức tạp mới, nhưng các nguyên lý của Twelve-Factor vẫn là nền tảng hữu ích cho platform builders hiện đại. Trong bối cảnh đó, Factor VI có thể được hiểu hiện đại hơn như sau: hãy để orchestration platform tự do thay, dời, nhân bản hoặc phục hồi process của bạn mà không làm sai logic ứng dụng. Đó là cách đọc hiện đại rất tự nhiên của “stateless processes”.
Tuy vậy, cần phân biệt rõ:
- Nguyên lý gốc: app chạy như một hoặc nhiều process stateless; state bền vững phải ra backing service.
- Diễn giải hiện đại: container, Pod, Deployment, autoscaling và self-healing của platform sẽ phát huy tốt hơn nhiều nếu app process thật sự stateless.
14) Checklist tự đánh giá
Hãy tự hỏi về hệ thống của bạn:
- Có dữ liệu nghiệp vụ hoặc workflow progress nào đang nằm trong RAM của app process không?
- Có chỗ nào đang ghi file local rồi kỳ vọng lần sau app vẫn đọc lại được không?
- App có đang dùng sticky sessions hoặc phụ thuộc vào request sau quay lại đúng instance cũ không?
- Khi kill một
webprocess hoặcworkerprocess bất kỳ, hệ thống có còn đúng không? Đây là suy luận thực hành trực tiếp từ yêu cầu stateless/share-nothing của Twelve-Factor. - Nếu đang chạy trên Kubernetes, workload của bạn có đang được đặt nhầm vào Deployment dù thật ra cần StatefulSet, hoặc ngược lại không?
Nếu có từ 2 câu trở lên khiến bạn lấn cấn, Factor VI của app đó đang chưa khỏe.
15) Tóm tắt nhanh
- Process của Twelve-Factor phải stateless, share-nothing.
- State bền vững phải nằm ở backing services, không nằm trong RAM hay local disk của process.
- Memory và filesystem local chỉ dùng như cache ngắn hạn cho một transaction/job.
- Sticky sessions là vi phạm; session state nên đi vào datastore phù hợp như Redis hoặc Memcached.
- Heroku dyno và Kubernetes Deployment/StatefulSet là hai ví dụ rất rõ để nhìn ra giá trị thực chiến của nguyên tắc này.