Overview
Thefeature middleware provides feature flag support for controlled rollouts, A/B testing, and gradual feature deployment. It supports static flags, in-memory providers, and custom providers.
Installation
Quick Start
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
Provider | Provider | Static | Flag provider |
Flags | Flags | - | Static flags map |
Flag Structure
Examples
Static Flags
Check Flag in Handler
Get Flag Details
Memory Provider (Dynamic)
Require Flag Middleware
Require All Flags
Require Any Flag
Custom Provider
User-Specific Flags
Percentage Rollout
List All Flags
Flag with Metadata
API Reference
Memory Provider Methods
Technical Details
Architecture
The feature middleware uses a provider-based architecture that allows flexible feature flag management:- Context Storage: Feature flags are stored in the request context using a private
contextKey{}type for isolation - Provider Interface: The
Providerinterface defines a single methodGetFlags(c *mizu.Ctx) (Flags, error)enabling custom implementations - Thread Safety: The
MemoryProviderusessync.RWMutexfor concurrent read/write access - Immutable Returns: Providers return copies of flag maps to prevent external modification
Implementation Details
Flag Resolution Flow:- Middleware intercepts request
- Providerβs
GetFlags()is called with context - Flags are stored in request context
- Helper functions (
IsEnabled,Get, etc.) retrieve flags from context - On provider error, empty flag map is used (fail-safe behavior)
- Wraps a
Flagsmap in an immutable provider - Returns defensive copies to prevent modification
- Zero overhead after initialization
- Mutable in-memory flag storage
- Uses read-write mutex for concurrent access
- Methods:
Enable(),Disable(),Toggle(),Set(),SetFlag(),Delete() - Safe for runtime flag updates
Require(name, handler): Guards route requiring single flagRequireAll(names, handler): Guards route requiring all flags enabledRequireAny(names, handler): Guards route requiring at least one flag enabled- Custom handlers provide fallback responses when flags are disabled
Performance Characteristics
- Static Provider: O(n) copy operation per request where n is flag count
- Memory Provider: O(n) copy with RLock, write operations use Lock
- Flag Lookup: O(1) map lookup from context
- Context Storage: Single context value, minimal memory overhead
Best Practices
- Use descriptive flag names
- Document flag purposes
- Clean up old flags after rollout
- Use percentage rollouts for risky features
- Implement a custom provider for production
- Include metadata for analytics
Testing
The feature middleware includes comprehensive test coverage for all functionality:| Test Case | Description | Expected Behavior |
|---|---|---|
TestNew | Static flags with enabled/disabled states | Correctly identifies enabled and disabled flags |
TestIsDisabled | Check if flag is disabled | Returns true for disabled flags |
TestGetFlags | Retrieve all flags from context | Returns complete flag collection |
TestGet | Retrieve specific flag with metadata | Returns flag with description and metadata intact |
TestRequire (enabled) | Route protection with enabled flag | Allows request to proceed (200 OK) |
TestRequire (disabled) | Route protection with disabled flag | Blocks request with 404 Not Found |
TestRequire_CustomHandler | Custom handler when flag disabled | Executes custom handler returning 403 Forbidden |
TestRequireAll | Require multiple flags all enabled | Allows request when all flags enabled |
TestRequireAny | Require at least one flag enabled | Allows request when any flag is enabled |
TestMemoryProvider | In-memory provider CRUD operations | Enable, Set, and SetFlag work correctly |
TestMemoryProvider_Toggle | Toggle flag state at runtime | Switches flag from enabled to disabled |
TestMemoryProvider_Delete | Delete flag from provider | Flag no longer exists after deletion |
Related Middlewares
- multitenancy - Multi-tenant support
- version - API versioning