Skip to content

Modern React 40: Deployment, observability, and feature flags

This is part 40 of the Modern React development series.

A React app changes character in production. Bundles are optimized, users have slower devices, networks fail, errors need reports, and feature rollouts need control. Deployment work gives the app feedback loops after it leaves a developer machine.

Concept

Deployment ships the built app to users. Observability collects signals about what the app is doing. Feature flags control whether a capability is visible or active for a user, cohort, environment, or rollout stage.

Terms

  • Deployment: The process of building and publishing an application for users.
  • Observability: Telemetry that helps teams understand runtime behavior through logs, metrics, traces, errors, and events.
  • Feature flag: A runtime switch that controls a feature without requiring a new build.
  • Web vitals: User experience metrics for loading, responsiveness, and visual stability.
  • CI: Continuous integration, an automated environment that runs checks for a change.
  • PII: Personally identifiable information, data that can identify a specific person.

Mental model

Think of production as a long-running experiment with instruments. Deployments change the system, observability tells you what changed, and flags let you narrow or reverse exposure.

How it is used

Use this layer for production error reporting, performance monitoring, release gates, gradual rollouts, A/B tests, kill switches, analytics events, and identifying regressions after a React or framework upgrade.

How to use it

  1. Build the app with the production command used by CI.
  2. Report root errors and route errors to an error service.
  3. Measure key user flows and web vitals.
  4. Read feature flags from a provider or server boundary, then pass simple booleans or variants into UI.
  5. Keep server-side authorization separate from client feature visibility.

Example: Root error reporting

import { createRoot } from "react-dom/client";
const root = createRoot(document.getElementById("root")!, {
onCaughtError(error, errorInfo) {
reportError({
name: "react-caught-error",
message: error.message,
componentStack: errorInfo.componentStack,
});
},
});
root.render(<App />);
Browser result
const root = createRoot(document.getElementById("root")!, {
  onCaughtError(error, errorInfo) {
    reportError({
      name: "react-caught-error",
      message: error.message,
      componentStack: errorInfo.componentStack,
    });
  },
});
root.render(<App />);

React root options provide one place to report production render errors caught by boundaries.

Example: Feature flag as a prop

import { ClassicPaymentForm } from "./ClassicPaymentForm";
import { NewPaymentSheet } from "./NewPaymentSheet";
type CheckoutPageProps = {
flags: {
newPaymentSheet: boolean;
};
};
export function CheckoutPage({ flags }: CheckoutPageProps) {
return flags.newPaymentSheet ? (
<NewPaymentSheet />
) : (
<ClassicPaymentForm />
);
}
React output

New payment sheet

The component receives a simple decision. The flag system can live at the server, provider, or route boundary.

Details to watch

  • Build parity: CI should run the same production build command used for deployment.
  • Flag cleanup: Expired flags become permanent complexity. Track owners and removal dates.
  • Telemetry privacy: Telemetry should avoid personally identifiable information unless the system is designed and approved for it.
  • Client visibility: A feature flag can hide UI, but it is not authorization.

Series navigation

References