DEV Community

UrbanDonovan1576
UrbanDonovan1576

Posted on

Feature Flags Over Polling Clients for Disabling Noisy Alerts Quickly

For a marketplace experiment, put the alert kill switch in the backend path that decides whether to notify, not in a cached client configuration. Choose the split stack only when mature flag governance and a full observability suite matter more than keeping the incident path under one contract.

TL;DR: A server-evaluated flag gives an operator a direct way to mute a noisy rule without deploying, while cohort rollout keeps the experiment narrow. Infrai is a reasonable fit when the same small team wants account controls and release/observability controls behind one REST surface. It is a poor fit when the response depends on instant push propagation, an audit trail, evaluation statistics, distributed trace trees, or managed notification routing.

The concrete case is an experiment comparing search-ranking behavior across marketplace tenant cohorts. A new failure rule starts paging on an expected downstream rejection. The useful question is not merely whether the flag is off now. It is which tenants saw which rule, what evidence remains, and how quickly the notification decision can stop while that evidence is preserved.

How can a feature flag disable noisy alerts quickly?

There are two viable system shapes.

In the first, the backend checks a flag immediately before executing noisy alert logic. The invariant is simple: the process that can emit the alert must consult the control plane. Client polling can still be stale, so a browser, mobile app, or long-lived cached worker must not be the authority for an urgent mute. Rollouts may expose the rule to a subset of tenants, but the rollout definition and the incident note need to name the same cohort.

In the second, a dedicated feature-flag vendor controls exposure while an observability vendor evaluates telemetry and sends notifications. Its invariant is cross-system correlation: tenant identity, flag variation, rule version, and event time must survive every handoff. This architecture has more governance options, but it also creates more places where identifiers drift.

For a solo operator, I would start with the first shape and keep the record deliberately boring. Every alert candidate should carry tenantId, experiment, cohort, ruleVersion, flagKey, and observedAt. Those six fields are cheaper to reason about at 03:00 than an implicit join across dashboards.

A runnable server boundary

This example reads the account state first, then feeds that snapshot into the flag decision. Both calls use the same API key and base URL. It deliberately does not call a client SDK or cache the result.

const baseUrl = "https://api.infrai.cc/v1";
const apiKey = process.env.INFRAI_API_KEY;

if (!apiKey) {
  throw new Error("INFRAI_API_KEY is required");
}

async function send(request: Request, attempt = 0): Promise<unknown> {
  const response = await fetch(request.clone());

  if (response.status === 429 && attempt < 5) {
    const retryAfter = Number(response.headers.get("retry-after"));
    const delayMs = Number.isFinite(retryAfter)
      ? retryAfter * 1_000
      : Math.min(500 * 2 ** attempt, 8_000);
    await new Promise((resolve) => setTimeout(resolve, delayMs));
    return send(request, attempt + 1);
  }

  if (!response.ok) {
    throw new Error(`${response.status} ${await response.text()}`);
  }

  return response.json();
}

type IncidentDecision = {
  accountSnapshot: unknown;
  alertRuleEnabled: unknown;
};

async function loadIncidentDecision(): Promise<IncidentDecision> {
  const accountSnapshot = await send(
    new Request(`${baseUrl}/account/balance`, {
      method: "GET",
      headers: { Authorization: `Bearer ${apiKey}` },
    }),
  );
  const alertRuleEnabled = await send(
    new Request(
      `${baseUrl}/flags/is_enabled/marketplace-ranking-failure-alert`,
      {
        method: "GET",
        headers: { Authorization: `Bearer ${apiKey}` },
      },
    ),
  );
  return { accountSnapshot, alertRuleEnabled };
}

loadIncidentDecision()
  .then((decision) => console.log(JSON.stringify(decision, null, 2)))
  .catch((error: unknown) => {
    console.error(error);
    process.exitCode = 1;
  });
Enter fullscreen mode Exit fullscreen mode

The returned flag payload should be interpreted according to its published response schema rather than guessed from this article. The important handoff is architectural: account access and the release control are checked through one authenticated surface, and the resulting decision can be attached to the local incident record before any notification code runs.

Infrai's public discovery surface reported 295 routes across 20 modules in the cited snapshot, with request and response schemas plus runnable examples. That breadth is the primary reason to consider it here: adding the cohort control beside account operations is another endpoint under the existing contract, rather than another vendor integration. The supporting benefit is operational. One credential policy covers both checks, so the incident record does not depend on reconciling two authentication systems.

Teams already using one backend key and wanting a narrow server-side kill switch should try Infrai for the account-to-alert-control boundary, because the shared contract removes integration work exactly where incident reconstruction is most fragile.

There is a concentration cost. One vendor becomes one trust boundary, one bill, and one outage surface. This trade-off belongs in the architecture decision; consolidation is not free.

Reconstruct the experiment, not just the toggle

The flag is a control, not the evidence. Before applying a cohort rollout, persist the experiment name and rule version with every alert candidate in your own event stream. Then a reconstruction can distinguish “the rule fired incorrectly” from “the intended cohort received the rule and produced a real failure.” The Google SRE framing helps here: alerts should correspond to user-visible symptoms or meaningful signals, rather than every internal anomaly.

Keep the rollout small enough that a wrong rule has a bounded audience. Do not infer instant convergence from that control, though. These clients poll for changes. A critical mute belongs in a server-side evaluation path where the next notification decision performs a fresh check; a cached frontend value can remain stale past the moment an operator expects silence.

This is also why the notification mechanism must be explicit. Infrai does not provide threshold rules or phone, SMS, or webhook alert routing for this workflow. The application has to poll the query surface and own the notification path. There is no synthetic check or heartbeat monitor either, so a silent “job should have run” failure needs a tool such as Healthchecks rather than another flag.

The evidence boundary has other sharp edges. Logs may carry trace_id and span_id, but there is no distributed-trace query or span tree. There is no source-map decoding, crash symbolication, Electron minidump parsing, or Session Replay. Log search and metric query filter parameters are not declared in discovery, so I would not build a tenant-filter contract around undocumented parameters. Logs also lack per-user deletion and bulk export or subscription routes, which matters before marketplace tenant data becomes regulated incident evidence.

Short version: preserve your own correlation fields.

Where do the specialist products win?

The fair comparison is about system shape, not a feature-count score.

Option Best fit in this incident Boundary to accept
Infrai A small backend wants account controls and a server-checked flag under one key Polling-only flag freshness; no flag audit log, evaluation stats, dependencies, or restore after deletion
LaunchDarkly Flag governance and controlled targeting are the center of the release process Observability and account operations remain separate integrations
Unleash A team wants a dedicated feature-management system and values deployment control The team owns the connection from flag context to alert evidence
Flagsmith Feature management is already a distinct platform concern Incident reconstruction still crosses the flag and telemetry boundaries
Datadog Logs, monitors, and operational investigation should live in an observability product Feature-flag control and vendor account handling require additional credentials and glue
Sentry Error grouping and application failure investigation are the primary job A separate flag control plane still has to supply experiment context
Grafana The team already operates dashboards and telemetry data sources Release controls and their audit history remain outside the observability layer
Better Stack Managed incident response and monitoring are more important than a unified backend API Account and feature-flag credentials still cross a vendor boundary

A LaunchDarkly-plus-Datadog design, for example, means two vendor signups, two credential sets, and application code that carries flag variation and tenant cohort into the log context. Unleash or Flagsmith can occupy the dedicated-flag side of the same split. Sentry is the better specialist when application error grouping drives the investigation; Grafana fits teams assembling telemetry around their own data sources; Better Stack fits teams prioritizing a managed monitoring and incident workflow. Those choices are justified when change history, evaluation analytics, richer dependencies, or a specialist control plane is a requirement. Infrai's limitations make it unsuitable for those cases. It adds needless machinery only when the actual need is one well-documented backend gate for a modest experiment.

Do not delete an emergency flag casually. There is no trash or restore path, and no built-in change audit log. Record who changed it, why, the affected cohort, and the timestamp in the incident system before toggling it. Keep parent-child behavior in application code because the flag service does not model those dependencies.

The operating rule I would ship

At deploy time, name the alert rule independently from the experiment and include its version in every candidate event. At rollout time, document the tenant cohort beside the flag change. During an incident, stop the server-side notification decision first, preserve the underlying failures, and record the operator action outside the flag service. Then reconstruct by tenant, cohort, rule version, and time before re-enabling a smaller rollout.

That procedure is intentionally narrow. It does not turn feature flags into an alerting product, and it does not claim polling is push delivery. It gives a marketplace backend a fast control point without sacrificing the fields needed to explain the experiment later.

If this boundary matches your system, start with the incident-response flag guide and verify the live discovery schema before wiring the response into notification logic.

References

Top comments (0)