Feature flags need to be fast. You don't want an HTTP request every time your application asks:
"Is this thing turned on?"
That would be a spectacularly bad architecture. Let's look at what actually happens under the hood.
Microsoft.FeatureManagement: Let IConfiguration Do Its Thing
If you're using Microsoft.FeatureManagement, your feature definitions typically come from IConfiguration. A common setup looks like this:
{
"FeatureManagement": {
"NewFeature": true
}
}
The important thing to understand is that IConfiguration isn't reading appsettings.json from disk every time you ask for a value. Configuration providers load their data into the configuration system. .NET can watch for changes and reload configuration when the underlying source changes. So the flow looks roughly like this:
appsettings.json
↓
Configuration Provider
↓
IConfiguration
↓
Microsoft.FeatureManagement
↓
Your application
No disk read per feature check. No network request. Just an in-memory configuration lookup. Maybe you add your own caching layer. Maybe you don't. Either way, nice and boring.
And boring is good.
But What About Remote Feature Flags?
That's where things get more interesting. If your feature flag definitions live on another service, you obviously don't want this happening every time your application checks a flag:
Application
↓
HTTP
↓
Feature Flag Service
↓
HTTP response
↓
Application
Once or twice? Fine.
A few thousand times per second? Congratulations. You've invented a denial-of-service attack against your own feature flag provider. That's where caching comes in.
How FeatureFlags.app Caches Flags
The FeatureFlags.app client retrieves feature definitions over HTTP, but it doesn't make that HTTP request every time your application evaluates a flag. Instead, the client uses IMemoryCache to cache the complete set of feature definitions. The default cache expiration is 15 minutes, and you can configure it with:
{
"FeatureFlags": {
"CacheExpirationInMinutes": 15
}
}
There's also an explicit ClearCache() method when you need to force a refresh. So instead of this:
Every request
↓
Application → HTTP → FeatureFlags.app
You get something more like:
First request
Application
↓
Cache miss
↓
HTTP
↓
FeatureFlags.app
↓
Feature definitions
↓
Cache
Subsequent requests
Application
↓
Cache
↓
Feature definitions
Much less exciting for your network stack.
Which is the point.
The Trade-Off: Freshness vs Performance
Caching always involves a trade-off. With a 15-minute cache expiration, a feature flag change made in FeatureFlags.app may not immediately appear in every application instance. That's intentional. You're trading some freshness for performance and resilience.
If you need changes to propagate more quickly, you can lower the cache expiration. Or explicitly clear the cache when appropriate. There's another important detail if you're running multiple application instances:
IMemoryCache is local to each process.
So if you have five application instances, you effectively have five separate caches.
FeatureFlags.app
/ | \
/ | \
Cache Cache Cache
↓ ↓ ↓
App 1 App 2 App 3
Each instance refreshes its own cached feature definitions. That's worth remembering when you're wondering why one instance appears to have a different flag state from another during the cache window.
How Other Services Do It
Caching isn't the only approach. Some feature flag platforms use server-side SDKs that maintain feature flag state locally and receive updates through streaming. Instead of polling periodically, the service pushes changes to the SDK. The architecture looks something like:
Feature Flag Service
↓
Streaming Updates
↓
Local SDK
↓
Cached Rules
↓
Flag Evaluation
The important part is still the same:
Flag evaluations happen locally.
The application doesn't need to make a network request every time it checks a flag. This approach can provide extremely fast evaluations, rapid updates, and the ability to continue using the last known state if the feature flag service temporarily disappears. It's a great architecture. It's also considerably more sophisticated and potentially more expensive to build and operate.
Different Tools, Same Goal
There are several ways to implement feature flag caching:
Microsoft.FeatureManagement
Relies on .NET's configuration infrastructure.
Configuration
↓
Feature Management
↓
Application
FeatureFlags.app
Uses an in-memory cache with a configurable expiration time.
FeatureFlags.app
↓
HTTP
↓
IMemoryCache
↓
Feature Management
↓
Application
Streaming SDKs
Maintain locally cached rules and receive updates from the server.
Vendor
↓
Streaming Updates
↓
Local SDK Cache
↓
Flag Evaluation
Different implementations. Same fundamental goal. Don't make feature flag evaluation depend on a network round trip. Your application has enough exciting problems already.
If you're using .NET and want a simple way to manage remote feature flags while keeping evaluations local and fast, check out FeatureFlags.app. Your API server will appreciate the break.
Cache the flags. Not your regrets.
Top comments (0)