Error Boundary Placement

Error boundary placement determines how much of the component tree is replaced when an error occurs. Choosing the right boundary granularity balances fault isolation, user experience, recovery options, and implementation complexity.

An error boundary is a React component that catches rendering errors in its descendant tree and displays fallback UI instead of allowing the failed subtree to take down the entire rendered application. Placement determines the scope of that fallback: a high boundary can replace a large portion of the interface, while a lower boundary can isolate a smaller feature.

Place boundaries around meaningful independent UI regions rather than mechanically wrapping every component. For example, a dashboard might isolate its navigation, main content, and secondary panels so that failure in one area does not necessarily hide unrelated functionality. The appropriate boundary usually corresponds to a region where a useful fallback can be shown.

Boundary hierarchy matters when boundaries are nested. If a lower boundary handles an error, an ancestor boundary does not need to replace that subtree. If the lower boundary itself fails while rendering its fallback, an appropriate ancestor can provide another layer of protection. This creates a hierarchy of failure containment.

The placement should also reflect recovery behavior. A boundary around a route or page can offer a page-level retry or navigation action, while a boundary around a widget can preserve the rest of the page and provide a localized retry. Too few boundaries create large failure domains; too many can make fallback behavior fragmented and harder to reason about.

Key points

Interview questions

How would you decide where to place an error boundary in a React application?

I would start with user-visible regions that can fail independently and that have a meaningful fallback. A dashboard widget is a good candidate if the rest of the dashboard remains useful without it. I would also consider recovery actions, such as retrying a data-driven section or navigating away from a broken route. The goal is to isolate failures without creating unnecessary boundary complexity.

What happens if you put an error boundary very high in the component tree?

A high boundary can catch errors from a large descendant subtree that it is responsible for. When it handles an error, that larger subtree is replaced by its fallback UI. This can protect the application from an unhandled rendering failure, but it may hide unrelated UI that could otherwise remain usable. Therefore, high placement provides broad containment at the cost of coarser failure isolation.

Why might nested error boundaries be useful?

Nested boundaries allow different levels of the interface to have different recovery behavior. A local boundary can handle a widget failure without affecting its surrounding page. An ancestor boundary can provide additional protection if a lower-level boundary cannot handle the failure. This creates layered containment rather than relying on one fallback for the entire application.

What are the trade-offs between many small boundaries and a few large boundaries?

Many small boundaries can isolate failures precisely and preserve more of the interface, but they require more fallback states, recovery decisions, and testing. A few large boundaries are simpler to reason about but can replace useful UI when a localized failure occurs. I would choose boundaries according to product-level failure domains rather than arbitrary component boundaries. The design should also account for observability and how users can recover from each failure.