The Feature Flags driver, released in October, evaluates feature flags from Unleash, Flagsmith or GrowthBook within a Kipchak API. The announcement of that driver noted that a middleware to release features per API key was on the roadmap. The Feature Flag middleware is that middleware.
It is free and MIT-licensed. It places routes behind flags, so that a new endpoint, or a new version of one, can be released to some customers before others, and withdrawn without deploying the API again.
Routes behind flags
A gate is attached to a route or a group of routes:
$app->post('/v2/checkout', [Checkout::class, 'create'])->add(new Gate('new-checkout'));
While the flag is off for the customer making the request, the route answers 404, as if it did not exist, or 403 if configured. Gates can also be defined by path pattern and method in configuration, which suits a whole version of an API.
The same mechanism works in reverse as a kill switch. A gate with enabled: false blocks the route while the flag is on, so that an operation can be suspended from the flag service’s console during an incident. A gate can also require a particular variant of an experiment, so that only customers given that variant reach a route.
Each API key stays in or out
A percentage rollout releases a feature to, for example, 30 per cent of customers. For an API this is only useful if the same customer receives the same answer on every request. A customer whose integration sees an endpoint appear and disappear between requests cannot use it.
The middleware uses the consumer as the flag’s user: the client named for an API key, or the client_id of a token, as defined by Kipchak Identity. The flag service assigns each user to a rollout by a hash of that value, so each API key remains either inside or outside the rollout on every request and on every worker. The key itself is never sent to the flag service.
We tested this against real Unleash, Flagsmith and GrowthBook servers with a 30 per cent rollout over 1,000 API keys. The rollout admitted 30.6, 31.9 and 34.6 per cent of the keys respectively, and admitted the same keys on every repetition, including on newly started workers.
Targeting by plan, country or version
Flag services can target rules at attributes, such as “plan is pro” or “app version is at least 42”. The middleware builds those attributes for each request from token claims, request headers, values set by other middleware, or fixed values. Token claims keep their type, so a boolean claim remains a boolean and a list of roles remains a list. The tenant from Kipchak Identity is included automatically.
One answer for each request
A controller behind a gate can read the same flags:
$flags = FeatureFlags::of($request);
if ($flags->isEnabled('new-checkout')) {
// ...
}
Each flag is evaluated once per request and the answer kept, so the controller always sees the answer the gate acted on, even for a rollout that is not sticky.
When the flag service is unavailable
The Feature Flags driver continues to use the last flag definitions it fetched while the flag service is unavailable, so a running API keeps its gates. A worker that starts during an outage has no definitions. By default its gates then deny, as if each flag were off; they can instead be configured to allow requests, or to answer 503.
In worker-mode testing with eight workers, 9,000 concurrent requests across three flag services gave every API key the same answer in each of three rounds, and 2,000 interleaved requests showed no request receiving another request’s customer or attributes. With Unleash stopped, running workers continued to apply their gates correctly, and a change made to a flag in Unleash reached every worker within the five-second refresh interval.
Installation
The Feature Flag middleware is free and MIT-licensed. It requires the Feature Flags driver with a configured connection:
composer require kipchak/middleware-feature-flags
The configuration reference, including how to configure sticky rollouts in each flag service, is in the Feature Flag middleware documentation.