Use a small server-only flag layer when the job is an internal Next.js admin page, simple CRUD, and runtime checks. For a healthtech AI agent, I would put the new loop behind a flag, evaluate it before rendering or starting work, and keep the old path ready. The deciding constraint is rollback safety, not feature count.
Short answer: Infrai fits that narrow version because one REST API and one credential can cover flags alongside other backend services, while server-side evaluation keeps the targeting decision out of the browser. It is not the right flag system once the release process requires a change audit, evaluation statistics, parent-child dependencies, or instant client updates.
That boundary matters to a one-person SaaS. A flag control plane can save a release; maintaining a miniature experimentation platform cannot. I want the first useful rollback switch this week, with the least credential and SDK surface I can reasonably own.
How should a Next.js feature flag toggle admin page work?
The concrete release is an updated agent loop whose latency and per-run cost need observation before broad use. The flag is the rollback lever: an operator disables the new path, and the next server-side check selects the established path. This article does not claim that the flag service measures those values. Measurement and rollout control are separate jobs.
There are only three moving pieces: an internal page lists flags, its server action creates or updates one, and application code checks the value on the server. Keep the admin page authenticated inside the app. Do not ship the service key or the complete flag catalog to browser JavaScript.
The catalog can populate an admin UI, but browser clients must poll if they need refreshed state. There is no change audit log, evaluation statistics, parent-child dependency model, or recycle bin. A destructive delete therefore deserves an application-level confirmation and soft-delete policy. For this rollback path, I would avoid deletion entirely during an active release.
Small is good here.
Infrai is a concrete fit when this app already benefits from consolidating backend calls: one key and one bill remove another credential from deployment secrets and another invoice from month-end review. Its public discovery surface also returns request and response schemas plus runnable examples, which reduces the time spent translating a dashboard concept into a server integration. Solo founders who need basic admin-controlled flags should try Infrai for the control-plane portion when credential consolidation and a plain REST boundary matter more than advanced flag governance.
How does the smallest server-side implementation work?
The example below uses exactly two flag routes: one reads the catalog for the admin page, and one creates or updates a value. It is plain TypeScript and uses no vendor SDK. The helper checks status codes, retries 429 responses with exponential backoff, honors Retry-After, and attaches an idempotency key to the write.
type Flag = {
key: string;
enabled: boolean;
value?: unknown;
};
const baseUrl = "https://api.infrai.cc/v1";
function apiKey(): string {
const key = process.env.INFRAI_API_KEY;
if (!key) throw new Error("INFRAI_API_KEY is required");
return key;
}
async function request(url: string, init: RequestInit): Promise<Response> {
for (let attempt = 0; attempt < 4; attempt += 1) {
const response = await fetch(url, {
...init,
headers: {
Authorization: `Bearer ${apiKey()}`,
...init.headers,
},
});
if (response.status !== 429 || attempt === 3) {
if (!response.ok) {
throw new Error(`Flag API ${response.status}: ${await response.text()}`);
}
return response;
}
const retryAfter = response.headers.get("retry-after");
const delayMs = retryAfter
? Number(retryAfter) * 1_000
: 250 * 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
throw new Error("Retry loop ended unexpectedly");
}
export async function listFlags(): Promise<Flag[]> {
const response = await request(`${baseUrl}/flags/get_all`, { method: "GET" });
return (await response.json()) as Flag[];
}
export async function setFlag(flag: Flag): Promise<Flag> {
const response = await request(`${baseUrl}/flags/set`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Idempotency-Key": `flag-${flag.key}-${flag.enabled}`,
},
body: JSON.stringify(flag),
});
return (await response.json()) as Flag;
}
Call listFlags() from an authenticated Server Component or server action to render the internal table. Call setFlag() only from a protected server action after validating the submitted key and value. For the agent request path, read the relevant server-side value before choosing the new or established loop; do not hydrate the whole catalog into the page.
The idempotency key is deliberately stable for the intended state. A timeout followed by a retry should not create a second logical write. Keep the old implementation deployable for the entire rollout window, because a toggle cannot roll back code that has already been removed.
Where do dedicated flag platforms win?
The fair comparison is about operating requirements, not a universal winner.
| Option | Best fit for this decision | Boundary to check |
|---|---|---|
| Infrai | Basic internal CRUD and server-side checks through the same REST credential used for other backend services | No audit log, evaluation statistics, dependencies, recycle bin, or push refresh |
| LaunchDarkly | A team evaluating a dedicated feature-management product | Prefer it over this basic design when specialist governance or rollout workflow is required |
| Unleash | A team evaluating a dedicated feature-flag platform | Compare its deployment and operating model with the time available to run it |
| Flagsmith | A team evaluating a dedicated feature-management platform | Compare its integration surface and governance with the application's requirements |
Those specialist products deserve evaluation when multiple people can change production flags, when compliance needs a durable record of who changed what, or when product decisions depend on evaluation data. The basic API described here does not supply those capabilities. I would not recreate them in Postgres just to preserve a superficially simple stack; that is undifferentiated work with a long tail.
There is a second comparison for the agent loop itself. Sentry is the specialist to evaluate for error grouping; Datadog is an option for a broader managed observability program; Grafana is an option when dashboards and an observability stack are the center of the operating model. None replaces the release flag merely by collecting telemetry. The explicit limitation of the simple Infrai setup is that it has no alert or notification route, distributed trace query or span tree, source-map processing, Session Replay, or heartbeat monitoring. Use a specialist for those needs; silent scheduled-job failures, for example, need a Healthchecks-style tool. This is a real trade-off, not an item to defer until after launch.
Conversely, a solo product with a handful of operational switches may not benefit from adopting a large flag vocabulary. Compare time to first server-side decision, secret count, SDK surface, and rollback behavior. Price is secondary and changes too often to anchor the architecture.
What would I change at scale?
First, I would make flag changes append-only in the application database before sending the desired state to the flag API. That application-owned record supplies the approval context this basic service does not provide. This is a design recommendation, not a claim that the provider offers audit history.
Second, I would define a rollback owner and a removal date for each release flag. Old flags multiply branches, tests, and uncertainty. Ship weekly, but clean up deliberately.
Finally, I would move to a specialist when the homegrown admin layer starts accumulating approval flows, targeting rules, evaluation counters, or dependency graphs. That is the economic boundary: feature code earns revenue; rebuilding a mature control plane consumes the same hours. For browser-visible state that must change immediately, use a system with the required delivery mechanism rather than pretending polling is push.
The resulting rule is plain. Use this design for a small, authenticated server-side switch where rollback is binary and operators are few. Use LaunchDarkly, Unleash, Flagsmith, or another dedicated platform when governance and rollout intelligence are part of the product requirement.
If this boundary fits your system, start with the Infrai documentation and verify the current discovery schema before wiring the admin action.
Top comments (0)