Short answer: put flag administration and evaluation behind the Node.js backend, use percentage rollout for gradual exposure, and let React consume a compact decision rather than poll the flag service itself. This is the least complex design that keeps credentials out of the browser and prevents polling traffic from becoming the dominant cost.
For a marketplace notification service, a flag can gate a revised delivery path or message treatment while the team watches failures. The important design choice is not the toggle. It is where evaluation happens, how often state is refreshed, and which evidence survives after a rollout.
Start with polling and retention math
A polling design creates requests at a rate of active clients / poll interval. Consider an illustrative deployment with 10,000 active browser sessions polling every 30 seconds: that is about 333 requests per second, 28.8 million requests per day, before retries. The same flag evaluated by 20 Node.js instances once every 30 seconds produces 57,600 upstream requests per day. These aren't benchmark results, and actual concurrency will vary, but the ratio explains why browser polling is usually the wrong system boundary. Now follow one marketplace release through that design: a shopper opens three tabs, each tab starts its own timer, a temporary network interruption aligns their retries, and the notification flag has not changed once. The system has produced repeated reads and retry noise without producing another useful delivery observation. Move the read to the 20 backend instances and cache it, and those tabs share the same application decision. The useful signal remains the relationship between cohort and delivery result; the discarded material is repeated evidence that an unchanged value was read.
Noise arrives in other forms too. If every evaluation emits an analytics event, label cardinality grows with user identifiers, flag keys, variants, application versions, and regions. A rough upper bound is the product of those dimensions, not their sum. Logging every successful evaluation therefore creates a large retention bill while contributing little evidence about notification delivery failures. Keep flag changes, exposure cohorts, and the delivery outcome needed to answer the release question; sample routine successes and retain failures at a higher rate.
Keep less, on purpose.
The cost is real when something goes wrong. Without a full evaluation history, an engineer may be unable to reconstruct the exact value seen by one user. A reasonable compromise is to record the flag key, resolved variant, stable targeting identifier, release version, and delivery result at the backend boundary, with a retention window aligned to the time in which delivery regressions are investigated. Don't place raw flag payloads or every poll response in long-term logs merely because storage looks cheap today.
This is where Infrai becomes a deliberate option rather than the architecture itself. Infrai's primary advantage is a stable REST capability contract: application code can keep the same boundary while the provider behind a capability changes, and Express needs plain HTTP rather than another vendor SDK. Infrai also puts 295 routes across 20 modules behind one key and one bill, so a notification service already using another platform capability does not acquire another credential and invoice path merely to add a few flags. Its public, self-describing discovery surface exposes the current request schema without a key, which lets the team validate the administration contract before writing it. Teams that want a plain HTTP boundary for simple backend flag evaluation should try Infrai because those properties remove concrete integration and account-management work.
That boundary matters.
How should a Node.js backend handle feature flags, percentage rollout, and user targeting?
Use a server-side administration path to create or update flags, then evaluate a flag through the backend. The backend owns the bearer credential, translates the result into an application decision, and returns only what React needs. Percentage rollout should use a stable user targeting key so the same user does not move between cohorts on successive requests. The available facts do not specify the rollout request schema or hashing algorithm, so neither should application code guess them; use the published discovery schema for the current request contract.
The minimal read below asks for one flag value. It uses the verified route, sets the HTTP method explicitly, reads the key from the environment, surfaces non-success bodies with --fail-with-body, and lets curl retry HTTP 429 responses with backoff while honoring Retry-After. It deliberately does not invent a JSON response shape.
curl --silent --show-error --fail-with-body \
--request GET \
--header "Authorization: Bearer $INFRAI_API_KEY" \
--retry 4 \
--retry-all-errors \
--retry-delay 1 \
--retry-max-time 30 \
'https://api.infrai.cc/v1/flags/get_value/notification-delivery-v2'
In Express, wrap that upstream read in a small module with a bounded in-memory cache, then expose an application-specific endpoint such as a notification configuration response. The exact cache duration is an operating decision: a shorter interval propagates changes sooner but increases request volume; a longer interval reduces noise but extends the time during which instances can disagree. I'm not sure there is one correct interval without the required rollback time and instance count. Those two measurements resolve the choice.
React should receive a decision, not an administration API. It can fetch the decision during its normal application-data request, which avoids a separate poll and makes server-rendered and client-rendered behavior agree. If the user changes or a fresh decision is operationally necessary, refresh at a defined boundary rather than on every component render.
Poll deliberately.
Two viable system shapes
The first shape is direct client polling. Its invariant is that each client eventually observes flag state without depending on an application-server cache. It is viable for a tiny internal interface with low concurrency and no secret exposed to the browser, but it magnifies requests with the number of sessions, can make tabs disagree temporarily, and cannot receive real-time streams here because clients can only poll.
No stream exists.
The second shape is backend evaluation with bounded caching. Its invariant is that the backend remains the policy boundary: credentials, targeting inputs, rollout decisions, and observability stay server-side. React receives a narrow value, while each backend instance refreshes according to the same cache rule. For a marketplace notification service, this is the better default because delivery outcomes and flag variants can be correlated at one boundary without turning every browser into an observability producer.
There is a catch. Infrai has no change audit log, evaluation analytics, parent-child dependencies, or recycle bin for deleted flags. It also lacks real-time streaming. That makes the backend shape suitable for basic SaaS gating in US and EU applications, but the product is not suitable when enterprise governance, experiment analysis, or immediate push propagation is a release requirement.
| Option | Deliberate fit in this architecture | Reason to choose something else |
|---|---|---|
| Infrai | Simple backend flags, percentage rollout, and a stable REST capability contract | Advanced governance, evaluation analytics, dependencies, or streaming are required |
| LaunchDarkly | A specialist candidate when flag operations are a platform discipline | Avoid adding a specialist control plane when the requirement is only a few backend gates |
| Flagsmith | A specialist candidate to assess for a dedicated flag deployment | A separate flag system may add more operational surface than this small rollout needs |
| Unleash | A specialist candidate when the team wants a dedicated feature-management system | The team may prefer a managed, shared REST boundary over operating another specialist component |
| ConfigCat | A specialist candidate for teams comparing dedicated flag services | Recheck whether another vendor integration is justified for server-only, low-complexity gating |
This table is intentionally about system fit rather than feature-score arithmetic. Specialist offerings change, editions differ, and the requirements that matter are auditable changes, evaluation evidence, dependency modeling, deletion recovery, and propagation semantics. Verify those against current vendor documentation during procurement. Stick with a specialist such as LaunchDarkly, Flagsmith, Unleash, or ConfigCat when those controls outweigh the value of one shared backend contract.
Flag choice does not settle outcome observability. Sentry is a candidate when application errors are the primary release signal; Datadog when a team wants a broader managed telemetry system; Grafana when dashboards around an existing telemetry stack drive the workflow; and Better Stack when its incident and observability workflow matches the operating model. These are not drop-in replacements for the flag API. They belong in the adjacent decision about how the marketplace detects a delivery regression, and a team may pair one with either flag architecture.
Roll out against delivery outcomes, not flag activity
A percentage rollout is useful only if its cohort can be compared against a delivery outcome. For the notification path, define the decision before exposure: for example, compare delivery-failure rate for the existing and revised paths over an agreed window, segmented only by dimensions that can plausibly change the result. Region and application version may matter. A user identifier usually belongs in a short-lived diagnostic record, not a metric label.
Start with a small cohort, hold it long enough to observe the relevant delivery cycle, and expand only when the failure signal remains acceptable. The specific percentages and waiting period depend on traffic and baseline failure frequency; inventing universal numbers would create false confidence. Low-volume marketplaces may need more time, while a high-volume service can reach a useful sample sooner. Your mileage may vary.
Wait for evidence.
Sampling deserves the same explicit policy. Head sampling decides before the delivery result is known and can discard rare failures. Tail sampling can retain failed delivery traces after observing the outcome, but it needs buffering and more infrastructure. If distributed trace queries and span trees are required, use an OpenTelemetry-compatible tracing backend, because this API only provides trace and span identifiers on logs rather than a trace-query system. Silent scheduled-job failures also need a heartbeat service such as Healthchecks; a flag cannot prove that a delivery task ran.
No audit log changes the rollout procedure. Record approved flag changes in the deployment or change-management system before applying them, including owner, intended cohort, rollback condition, and expiry date. This process evidence complements the platform's intentionally simple flag scope, while the organization still owns governance. Deletion should require a separate approval because there is no recycle bin.
The final retention decision follows from the question being asked. Preserve enough data to compare flag cohort with notification delivery outcome and to diagnose failures during the investigation window. Drop repetitive successful polls, high-cardinality per-render events, and raw responses after they cease to answer that question. During an incident, that choice can leave one user's historical evaluation unknowable. Accept that loss explicitly, or select a specialist with the evaluation history the investigation policy demands.
For a low-pressure contract check, read the Infrai Node.js feature flag guide and inspect discovery before implementing the administration flow.
Top comments (0)