feat: implement per-organization feature flag system#135
Open
Phantomcall wants to merge 1 commit into
Open
Conversation
- Add feature_flags table migration with unique constraint
- Add FEATURE_NOT_ENABLED error code (403)
- Create featureFlagService with Redis caching (60s TTL)
- Create requireFeature('flag_name') middleware
- Add admin CRUD routes for managing flags per org
closes Pidoko257#114
|
@Phantomcall Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Per-Organization Feature Flag System
Problem
ProxyPay needs to roll out new features to specific organizations before general availability. Without a feature flag system, enabling/disabling features requires code changes and deployments, making gradual rollouts and targeted testing impractical.
Solution
Implement a feature flag system backed by PostgreSQL with Redis caching. Flags are stored per organization, cached in Redis with a 60-second TTL, and evaluated via Express middleware. An admin API enables/disables flags per organization without a deployment.
Changes
New Files
migrations/20260630_create_feature_flags_table.sqlfeature_flagstable withorganization_id,flag_name,enabled, unique constraint, indexes, and auto-update triggersrc/services/featureFlagService.tssrc/middleware/featureFlag.tsrequireFeature('flag_name')middleware — resolves org fromreq.userorreq.jwtUser, returns 403 on disabled flagsrc/routes/featureFlags.tsGET /(list by org),PUT /:flagName(upsert),DELETE /:flagName(remove)Modified Files
src/constants/errorCodes.tsFEATURE_NOT_ENABLEDerror code (403)src/index.ts/api/admin/feature-flagsHow It Works
feature_flagstable stores(organization_id, flag_name, enabled)with a unique constraint on the pair.feature_flag:{orgId}:{flagName}is checked first (60s TTL). On cache miss, the DB is queried and the result is cached. Writes update both DB and Redis.requireFeature('flag_name')is an Express middleware factory. It resolves the requesting organization fromreq.user.id(admin API key) orreq.jwtUser.userId(user JWT). If the flag is disabled, returns 403 withERR_FEATURE_NOT_ENABLED.GET /api/admin/feature-flags?organizationId=<id>— list all flags for an orgPUT /api/admin/feature-flags/:flagName— upsert a flag ({ organizationId, enabled })DELETE /api/admin/feature-flags/:flagName— delete a flagAcceptance Criteria
feature_flagstable stores flag name, organization_id, and enabled booleanrequireFeature('flag_name')checks the flag for the requesting orgERR_FEATURE_NOT_ENABLEDUsage Example
closes #114