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
- Build the app with the production command used by CI.
- Report root errors and route errors to an error service.
- Measure key user flows and web vitals.
- Read feature flags from a provider or server boundary, then pass simple booleans or variants into UI.
- 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 />);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 /> );}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
- Previous: Part 39: Internationalization and formatting
- Next: none. This is the end of the series.
- Series index: Modern React development