Hãy tưởng tượng kịch bản này: bạn là nhà phát triển Rails và đã dành vài ngày qua phát triển tính năng tuyệt vời mà mọi người đang mong đợi. Nó lớn và phức tạp, nhưng đã qua kiểm thử nghiêm ngặt, nên bạn tin mọi thứ hoạt động như nên. Có deadline phải tuân thủ, nên bạn deploy. Ngay lập tức, mọi thứ rối loạn.
Tính năng của bạn thẳng thừng làm hỏng toàn bộ ứng dụng cho một số user. Khó nói tại sao. Không có bug nào xuất hiện trong testing. bạn revert thay đổi, nhưng thiệt hại đã xảy ra. Khách hàng không hài lòng, và bạn sẽ dành thời gian dự kiến sửa chữa thiệt hại và điều tra sai sót.
Vấn đề là việc phát hành thay đổi phức tạp vốn dĩ rủi ro, không importa bạn test kỹ cỡ nào. Thật tốt nếu bạn đã triển khai tính năng này dần dần, có thể chỉ cho một nhóm nhỏ user trước. Sẽ tốt hơn nữa nếu bạn có thể tắt tính năng ngay khi vấn đề đầu tiên xuất hiện.
Đây chính là nơi feature flags (cờ tính năng) xuất hiện. Trong bài viết này, chúng ta sẽ đi sâu vào chi tiết feature flags trong Rails, bao gồm cách thiết lập chúng dùng gem Flipper. Nhưng trước hết: chúng là gì?
Feature Flags trong Ruby on Rails là gì?
Feature flags là cách bật hoặc tắt một tính năng trong ứng dụng trong khi nó đang chạy. Nếu cờ được bật, tính năng được dùng. Ngược lại, nó không được dùng. Hãy tưởng tượng pseudocode như sau:
Tên 'feature flag' hơi gây hiểu lầm. Kiểm soát hành vi ứng dụng tại runtime (thời gian chạy) không giới hạn ở tính năng, mà áp dụng cho bất kỳ hàm nào trong chương trình. Bạn có thể dùng feature flags để thử tinh chỉnh hiệu năng và chạy A/B test, ví dụ. Khác biệt đáng kể giữa feature flag và bất kỳ điều kiện (conditional) cũ nào khác là bạn có thể sửa đổi feature flags tại runtime.
Để minh họa, hãy tưởng tượng cơ chế feature flagging đơn giản dùng biến môi trường (environment variables).
Bằng cách sửa đổi giá trị biến môi trường, chúng ta có thể bật/tắt phần của ứng dụng theo ý muốn. Phần nào của ứng dụng? Bất cứ thứ gì bạn muốn!
Bạn có thể ẩn phần UI nếu tính năng bị tắt. Bạn có thể thay đổi phần mã, rất hữu ích nếu bạn không tự tin vào refactor mới. Một trong những cách dùng feature flags yêu thích của tôi là ẩn toàn bộ route dùng routing constraint:
Chúng ta đã thấy có rất nhiều ứng dụng cho feature flags. Triển khai naїve của chúng ta có một điểm yếu đáng kể, tuy nhiên. Một tính năng hoặc là bật, hoặc là tắt cho mọi user.
Điều gì nếu chúng ta muốn khả năng bật tính năng chỉ cho user cụ thể hoặc nhóm user, hoặc chỉ một phần thời gian? Hãy xem Flipper.
Dùng gem Flipper cho Feature Flags
Flipper là gem làm cho feature flags và các cách khác nhau để bật/tắt chúng có sẵn trong Rails. Nó mô-đun cao. Ngoài gem chính, bạn cũng phải chọn adapter lưu trữ (storage adapter) — nhưng nói sau. Hãy dùng adapter ActiveRecord cho lúc này.
Thêm các dòng sau vào Gemfile và chạy bundle install:
Khi dùng adapter ActiveRecord, Flipper sẽ lưu feature flag trong cơ sở dữ liệu và do đó yêu cầu thiết lập bảng cơ sở dữ liệu mới. Flipper đi kèm generator tiện lợi tạo migration cần thiết.
Bạn có thể dùng Flipper theo cách tương tự như triển khai naїve trước đó.
Khác biệt lớn là thay vì sửa biến môi trường, bạn giờ có thể bật/tắt tính năng dùng giao diện người dùng (UI) của Flipper. Thêm gem Flipper UI và cài đặt.
Sửa file routes để mount Flipper UI.
Nếu bạn khởi động ứng dụng và điều hướng đến Flipper UI, bạn sẽ thấy tổng quan tất cả tính năng có sẵn và trạng thái của chúng. Tiến hành tạo feature my_awesome_feature.

Các loại Feature Toggle trong Flipper
Bạn có thể đã nhận ra bạn có thể làm nhiều hơn chỉ bật/tắt tính năng trong Flipper UI. Flipper cho phép bật tính năng cho một tập con user hoặc thậm chí cho một phần trăm thời gian. Bạn có thể cấu hình feature flags dùng một trong năm cơ chế khác nhau.
Một trong đó là boolean toggle, công tắc bật/tắt toàn cục. Bốn cái còn lại thú vị hơn nhiều: groups (nhóm), actors (đối tượng), percentage of actors (phần trăm đối tượng), và percentage of time (phần trăm thời gian).
Groups (Nhóm)
Để bật tính năng chỉ cho một nhóm user cụ thể, dùng group toggle. Nếu chưa tồn tại, tạo file config/initializers/flipper.rb và thêm mã sau để đăng ký nhóm mới — ví dụ: user trả tiền (paid users).
Để dùng toggle mới này, sửa lời gọi Flipper để truyền user — hoặc actor, như tài liệu thích gọi — và tên tính năng.
Flipper sẽ dùng block bạn định nghĩa trong initializer để quyết định tính năng có bật cho user này không. Trong trường hợp này, nó sẽ gọi phương thức paid?. Bây giờ bạn có thể dùng nhóm này trong Flipper UI. Nhấn nút 'Add a Group' và chọn nhóm của bạn.

Nhóm của bạn không nhất thiết phải là user trả tiền. Có thể là thành viên team hoặc user đăng ký chương trình beta. Dùng group toggle hữu ích nếu bạn muốn phát hành thứ gì đó cho một tập con user. Hãy tưởng tượng bản phát hành beta hoặc internal release.
Actors (Đối tượng)
Đôi khi, bạn muốn phát hành thứ gì đó cho một cá nhân đơn lẻ. Trong trường hợp này, actor toggle là cái cần cân nhắc.
Bạn không cần thay đổi gì trong initializer để dùng cơ chế này. Tuy nhiên, bạn cần đảm bảo model actor — sẽ là model user hầu hết thời gian — triển khai flipper_id. Include Flipper::Identifier lo chuyện đó.
Bạn có thể dùng ID này để bật tính năng cho từng user riêng lẻ.

Feature toggle này tiện lợi nếu bạn muốn xem trước chức năng cho cá nhân cụ thể. Nghĩ đến việc bật tài khoản test cho partner cần truy cập tính năng trước khi phát hành rộng rãi.
Percentage of Actors (Phần trăm đối tượng)
Nếu bạn muốn tăng dần việc dùng tính năng, percentage of actors toggle là cho bạn. Hãy tưởng tượng bạn triển khai một số tối ưu hóa hiệu năng, và không chắc nó sẽ hành xử ra sao trong production. Bạn sẽ triển khai cho một phần trăm nhỏ user trước, sau đó tăng dần sử dụng trong khi giám sát ứng dụng.

Nếu mọi thứ đi sai hướng, bạn luôn có thể đặt phần trăm về zero.
Percentage of Time (Phần trăm thời gian)
Cuối cùng, bạn có thể bật tính năng cho một phần trăm yêu cầu. Bạn không cần cung cấp actor khi dùng toggle này.
Tôi thích dùng cái này để so sánh hiệu năng hai triển khai khác nhau. Lưu ý feature toggle này ngẫu nhiên. Cùng user sẽ trải nghiệm hành vi khác nhau trên mỗi yêu cầu.
Cấu hình nâng cao trong Flipper
Chúng ta đã thấy có thể dùng adapter ActiveRecord để lưu thông tin feature flag trong cơ sở dữ liệu. Nhưng tùy nhu cầu cụ thể, bạn có thể muốn dùng adapter khác.
Đối với hầu hết phần, tất cả bạn cần khi đổi storage adapter là cài gem tương ứng và cấu hình Flipper cho phù hợp. Ví dụ, nếu muốn dùng adapter Redis, thêm gem flipper-redis vào Gemfile và cập nhật initializer Flipper.
Ngoài cấu hình storage adapter, còn nhiều khía cạnh khác của Flipper bạn có thể tinh chỉnh.
Thêm feature flags gây ra chi phí hiệu năng nhẹ, nên thường bạn muốn thêm memoization và caching. Bạn cũng có thể muốn hạn chế truy cập Flipper UI chỉ cho user được ủy quyền. Những chủ đề này ngoài phạm vi bài viết, nhưng khuyến khích xem tài liệu Flipper nếu muốn đi sâu hơn.
Lưu ý khi dùng Feature Flags trong Rails
Feature flags tuyệt vời. Nhưng như nhiều thứ khác, có trade-offs (đấu tranh) cần cân nhắc.
Thêm feature flags và duy trì chúng tăng chi phí tổ chức (organizational overhead). Phát hành và triển khai tính năng ẩn dùng flags không đơn giản như deploy mã 'thông thường' — bạn phải nhớ bật nó, tất nhiên! Điều đó thường không quá khó, nhưng dọn dẹp feature flags không còn cần thiết có thể khó khăn.
Mỗi lần thêm feature flag vào mã, bạn thêm một điều kiện, và nếu không cẩn thận, mã nhanh chóng trở nên rối rắm bởi chúng. Theo dõi khi và tại sao bạn tạo feature flags nhất định có thể thách thức. Thật tiếc, Flipper UI bản thân không cung cấp nhiều công cụ quản lý feature flags.
Bạn cũng nên nhận thức rằng dùng feature flags sẽ gây ra chi phí hiệu năng nhỏ. Có cách giảm thiểu, nhưng có thể ảnh hưởng rõ rệt nếu cấu hình sai hoặc lạm dụng Flipper.
Tổng kết: Bắt đầu với Feature Flags trong Ruby on Rails
Chúng ta đã xem cách feature flags giúp bạn phát hành với niềm tin hơn, học cách chúng hoạt động về nguyên tắc, và thấy cách bắt đầu với feature flags dùng gem Flipper.
Có nhiều tình huống feature flags tiện lợi. Tùy trường hợp dùng, bạn có thể chọn một trong năm toggle khác nhau — boolean, group, actor, percentage of actors, hoặc percentage of requests.
Mặc dù làm việc với feature flags có nhược điểm và có thể mất thời gian quen, chúng vẫn là công cụ tuyệt vời để có trong tay.
Cho đến lần sau, happy coding!
P.S. Nếu bạn muốn đọc bài Ruby Magic ngay khi xuất bản, hãy đăng ký newsletter Ruby Magic của chúng tôi và đừng bỏ lỡ bất kỳ bài nào!