Feature Flags in Serverless Functions: The Poll That Never Fires
Your flag SDK polls every 20 seconds. Your function gets frozen at 40ms and thaws an hour later. Guess how many polls fired.
Every feature flag SDK is built for a long-lived process: fetch config at boot, refresh it on a timer, evaluate from an in-memory store so the hot path never touches the network. Serverless breaks the middle step. Lambda, Cloud Run and their equivalents suspend the execution environment between invocations — setInterval does not fire on a frozen container. It wakes up holding whatever config it had when it went to sleep, which might be minutes or hours out of date.
The obvious fix makes things worse. Constructing a client inside the handler puts a blocking config fetch on the critical path of every single invocation, and multiplies your config requests by your traffic. You have traded staleness for latency and a much larger bill.
There's a rollout problem underneath the caching problem too. Flipping a kill switch off is instant for a fleet of long-running pods. For a fleet of frozen containers thawing at unpredictable times, “instant” means whenever each one happens to wake up and notice.
The pattern that survives freezing
Build the client at module scope. Code outside the handler runs once per execution environment, not once per invocation. A warm container reuses the same client and the same in-memory store — evaluation stays a local lookup, and you pay for initialisation only on a cold start.
Let evaluation drive the refresh. A timer is the wrong trigger when time doesn't pass. The Featureflow Node SDK checks on every evaluate() whether the poll interval has elapsed since the last fetch, and kicks off a refresh if it has. The fetch runs alongside the invocation rather than blocking it, so a thawed container serves its current request immediately and picks up new config for the next one. One caveat: setting interval: 0 disables polling andthe lazy refresh with it. In serverless that's the one setting you don't want.
Pre-register failover variants. The genuinely cold invocation — new container, config not back yet — needs a defined answer. Pre-registering a feature with a failover variant means an unreachable or not-yet-loaded config evaluates to a variant you chose, rather than defaulting to off and quietly changing behaviour on a slice of your traffic.
import Featureflow from 'featureflow-node-sdk';
// Module scope: once per container, reused by every warm invocation.
const featureflow = new Featureflow.Client({
apiKey: process.env.FEATUREFLOW_SERVER_KEY,
application: 'checkout-fn',
withFeatures: [
// Known-safe variant if a cold start can't reach Featureflow yet
new Featureflow.Feature('new-checkout-flow', 'off').build(),
],
});
export async function handler(event) {
const user = new Featureflow.UserBuilder(event.customerId)
.withAttribute('plan', event.plan)
.build();
// evaluate() refreshes lazily when the container has been frozen past
// the poll interval — the timer didn't fire, but this call catches up.
return featureflow.evaluate('new-checkout-flow', user).isOn()
? checkoutV2(event)
: checkoutV1(event);
}Tag each function with an applicationname while you're there. Twelve functions sharing one environment key are indistinguishable in the dashboard otherwise, and knowing which workloads actually evaluate a flag is most of the work when you come to retire it. The Featureflow docs cover pre-registration and SDK configuration in full.
Serverless didn't remove the process — it just made the process unpredictable about when it runs. Put initialisation where it happens once, make refresh a consequence of work rather than of elapsed time, and decide up front what a function does when it knows nothing.
#FeatureFlags#Serverless#AWSLambda#ContinuousDelivery#NodeJS
Flags that keep up with cold starts
Start free with Featureflow — lazy config refresh, failover variants, and per-application SDK visibility.
Start Now (Free)Related Articles
Feature Flags and SSR: Stop the Flash of the Wrong Variant
The server renders one variant, the browser boots without flag state and repaints another. Evaluate on the server, bootstrap the client with the same answers, and first paint stops lying.
Feature Flags and the Login Boundary: Don't Let Sign-Up Reshuffle Your Variants
A visitor sees the new pricing page, signs up, and lands on the old one. Bucketing is a function of the user key — so carry the anonymous id across login, or your funnel experiments count one human as two.
Feature Flags in Background Jobs: Evaluate at Execution, Not Enqueue
Jobs run minutes or days after they're enqueued — and workers live for weeks. Evaluate flags per execution, key them on the job's subject so bucketing matches your web tier, and give every consumer a kill switch.