React Server Components: what changes for agency builds

React Server Components: what changes for agency builds
By Marco Lopes · April 12, 2023 · Web Development
React Server Components change a question we ask at the beginning of a build. Instead of assuming that every React component belongs in the browser, we can ask which parts genuinely need to run there.
At Kordspace, we work across software, AI, Web3, hardware, and design as a remote collaborative studio. That makes this more than a frontend curiosity. Where code runs affects integrations, hosting, security, collaboration, and the cost of maintaining what we ship.
Our view today is pragmatic: Server Components deserve serious evaluation, but not automatic adoption. The architecture is promising; the framework implementations and surrounding conventions are still developing. For agency builds, we need to understand both the opportunity and the delivery risk.
First, separate Server Components from server rendering
Server-side rendering, or SSR, produces HTML on the server so a browser can display a page before its JavaScript finishes loading. In a conventional React SSR application, the browser then hydrates the application to make it interactive. Much of the component code still needs to reach the browser.
React Server Components address a different concern: where components execute and which code enters the browser bundle. A Server Component runs on the server and contributes rendered output without shipping its own implementation as client-side JavaScript.
These approaches can work together. Server Components do not replace SSR, and choosing them does not mean abandoning interactive interfaces.
We find this distinction useful during discovery. “We already render on the server” does not answer whether a large formatting library, a database query, or a content transformation needs to become part of the browser application.
What is ready as of April 2023?
React Server Components are not something we can turn on across any existing React application with a small configuration change. They depend on framework and bundler integration, and the implementation surface is still experimental.
Next.js 13 offers a practical way to explore them through its beta app directory. Within that model, pages and layouts are Server Components by default, with Client Components introduced where browser-side behavior is required.
That beta label matters to our project planning. We should expect evolving APIs, library compatibility questions, and documentation that may change during a delivery cycle.
For an established production application, we would not propose a broad migration just to follow the latest architectural direction. For a new build with suitable requirements, we can run a bounded evaluation, document the risks, and decide whether the benefits justify adopting the beta tooling.
Design around interaction boundaries
The most useful architectural exercise is not sorting components into “big” and “small.” It is identifying where interaction begins.
Product descriptions, article bodies, account summaries, and navigation content may be good candidates for server execution. Search inputs, sortable tables, browser wallet connections, and device controls usually need client-side behavior.
In the Next.js model, the 'use client' directive marks a client entry point. Its imported component dependencies become part of the client module graph. Putting that directive near the top of the application can therefore pull much more code into the browser than intended.
We prefer narrow boundaries: keep the page and data assembly on the server, then pass a small, explicit set of props into an interactive component.
Composition also matters. A Server Component can pass server-rendered content as children to a Client Component. We do not need to convert an entire content region into client code merely because an interactive wrapper surrounds it.
Move data work closer to its source
Server Components can make some familiar frontend plumbing unnecessary. A component executing on the server can access a server-side data layer without first exposing a browser-facing endpoint solely for that component.
That can remove a round trip and simplify ownership. Instead of fetching data in an effect, managing an initial loading state, and synchronizing the result into component state, we can assemble the initial view on the server.
However, fewer API calls from the browser do not automatically mean a well-designed backend. We still want reusable data-access functions, explicit authorization, predictable error handling, and clear separation between presentation and business rules.
We also need to watch for waterfalls. If independent requests are awaited sequentially, moving them to the server merely relocates the delay. We should start independent work together, then use appropriate Suspense boundaries to reveal useful interface regions as they become available.
Keep the client contract small and safe
Props crossing the server-to-client boundary must be serializable by React’s transport. We favor simple data structures that make the boundary easy to inspect and test, rather than passing arbitrary class instances or ordinary callback functions from server code.
This is also a security boundary worth reviewing explicitly. A database object may contain internal notes, permission metadata, or fields that the interface never displays. Passing the entire object to a Client Component can still expose those fields to the browser.
Our rule is to construct a view model: send only what the interactive interface needs.
Keeping API credentials in server-only code is useful, but it is not a complete security strategy. We must still authorize access, validate inputs, avoid leaking sensitive errors, and remember that rendered output and client props are visible to the user.
Treat caching as application behavior
Caching deserves an architectural conversation, not a last-minute performance tweak. Next.js’s new data-fetching model integrates caching with server rendering, so familiar assumptions from browser fetch calls may not hold.
We should classify data before choosing a cache policy:
- Public editorial content may tolerate a revalidation interval.
- Product availability may need fresher reads than descriptive copy.
- Account details require user-aware handling and careful isolation.
- Administrative screens may prioritize freshness over reuse.
For request-time data in Next.js, options such as cache: 'no-store' can make the intended fetching behavior explicit. We should verify the actual route behavior rather than assuming every server fetch is fresh or every rendered page is safely shareable.
The practical test is simple: sign in as two different users, change data, navigate between routes, and inspect what each user receives. Performance improvements are not improvements if they produce stale decisions or cross-user exposure.
Plan mutations separately from reads
Server Components are particularly compelling for reading data and assembling a view. They do not, by themselves, give us a complete form submission or mutation architecture.
For builds today, we should plan writes through established mechanisms: API routes, route handlers where appropriate, or an existing backend service. Those endpoints still need authentication, authorization, validation, and a clear error contract.
After a successful write, the interface needs a deliberate update strategy. That might involve updating client state, refreshing server-rendered content, or invalidating relevant cached data through the framework’s available mechanisms.
We should not base a delivery estimate on experimental proposals becoming settled during the project. A working read path can look impressively simple while hiding unresolved questions about editing, optimistic feedback, retries, and cache freshness. Our technical spike should include a complete read-and-write journey.
Measure user experience, not architectural purity
Less client JavaScript is an opportunity, not a guaranteed performance result. A slow upstream service can still delay rendering, and a poorly chosen loading boundary can make a page feel fragmented.
We want measurements that reflect the actual build: transferred JavaScript, hydration work, server response time, loading behavior, and responsiveness during important interactions. We should compare representative routes against a baseline rather than claiming universal gains.
Design needs to participate here. Loading states affect layout, reading order, focus, and perceived stability. A skeleton that constantly shifts content can undermine the benefit of streaming.
We also audit component libraries early. Providers and browser-dependent widgets may require client wrappers, and library support for the new model varies. A small integration test can reveal whether our intended boundaries survive contact with the actual design system.
Choose hosting with the runtime in mind
Google Cloud is our preferred cloud platform, but the deployment choice should follow the application’s requirements. AWS and Azure can also fit, especially when an organization already has infrastructure, governance, or data services there.
For a Node-based Next.js deployment, a container on Google Cloud Run is one option we would evaluate. We would check streaming behavior through the complete request path, instance startup behavior, secrets management, database connectivity, and the consequences of scaling to multiple instances.
A server-rendered application with runtime data access is not equivalent to uploading static files to object storage. Cache coordination, connection limits, and observability become operational concerns.
We should also distinguish Node execution from edge runtimes. Dependencies that work in a Node process may not work in a more restricted runtime. Hosting diagrams need to show where each dependency actually executes, not simply label everything “serverless.”
Apply the boundary across our wider stack
The same reasoning helps with work beyond conventional content websites.
For AI features, we can keep provider credentials and server-side preparation away from the browser, while retaining client components for prompt input, cancellation, and interactive results. Long-running work still needs its own execution and delivery strategy.
For Web3 interfaces, public on-chain reads may fit server-side assembly, but wallet access and user signing belong with the browser’s wallet integration. Server Components do not remove that trust boundary.
For hardware-connected products, browser device APIs require client-side code where supported. Device authentication, telemetry storage, and command authorization remain separate backend responsibilities.
Across these cases, our goal is not “everything on the server.” It is putting each responsibility in an environment that can support it safely and predictably.
Make adoption a delivery decision
Remote collaboration works better when architectural choices are visible. We would record why the project uses Server Components, which framework version we have evaluated, where client boundaries belong, and which limitations remain unresolved.
Then we would build one representative vertical slice: a real data source, an interactive element, an authenticated path if required, a mutation, and a deployed environment. That gives design, engineering, and delivery a shared artifact to review.
Our short adoption checklist is:
- Confirm that beta framework risk fits the project and maintenance plan.
- Map server and client responsibilities before building shared components.
- Verify library compatibility and inspect the resulting client bundle.
- Test authorization, exposed props, caching, and post-write freshness.
- Validate loading states, failures, accessibility, and deployed streaming.
- Document a fallback approach and ownership for ongoing upgrades.
Server Components give us a useful new architectural tool, not a reason to rebuild every application. We want to use them where they simplify delivery and improve the experience, while keeping uncertainty visible. If you are planning a build and want to explore the right approach with Kordspace, start a project or read our related services pages.
Conversation (0)
No comments yet. Start the conversation.
Join the conversation
Create a free member account to comment.