Md Nazmus Shakib
Back to articles
Technology

Modern Data Fetching: Next.js Server Actions vs tRPC in Full-Stack Architecture

Md Nazmus Shakib

Md Nazmus Shakib

MERN Stack Developer

56m Total Read
Modern Data Fetching: Next.js Server Actions vs tRPC in Full-Stack Architecture

The architectural paradigm of building Full-Stack applications has shifted radically. For years, developers followed a strict boundary: build a backend REST or GraphQL API, and consume it via a frontend client using fetch or Axios. This process required maintaining API documentation, writing redundant TypeScript interfaces for both ends, and manually managing network serialization.

Today, two technologies are redefining this workflow by eliminating the traditional API layer entirely: tRPC (TypeScript Remote Procedure Call) and Next.js Server Actions. In this technical deep dive, we will analyze both approaches, compare their boilerplates, and determine which architecture is best suited for your next enterprise application.

1. tRPC: End-to-End Type Safety without Code Generation

tRPC allows you to write API endpoints as standard TypeScript functions on the server and call them directly from the client. Because both the client and server share the same TypeScript ecosystem (typically in a Monorepo), tRPC infers the return types and input validations instantly. If you change a database schema on the backend, your frontend code will immediately throw a TypeScript error if it breaks the contract.

tRPC heavily relies on Zod for runtime validation, ensuring that the data crossing the network boundary matches your TypeScript definitions perfectly.

tRPC Implementation Example
// 1. Server Side Router (server/routers/user.ts)
import { z } from 'zod';
import { publicProcedure, router } from './trpc';

export const userRouter = router({
  createUser: publicProcedure
    .input(z.object({ name: z.string(), email: z.string().email() }))
    .mutation(async ({ input }) => {
      // input is fully typed and validated at runtime
      const user = await db.user.create({ data: input });
      return { success: true, user };
    }),
});

// 2. Client Side Execution (components/CreateUser.tsx)
import { trpc } from '@/utils/trpc';

export function CreateUserForm() {
  // React Query wrapper provided by tRPC
  const mutation = trpc.user.createUser.useMutation();

  const handleSave = () => {
    mutation.mutate({ name: "Shakib", email: "hello@shakib.com" });
    // TypeScript will instantly error if 'email' is missing or misspelled
  };
}

2. Next.js Server Actions: The "API-less" Revolution

Next.js 14 fundamentally disrupted the React ecosystem by introducing Server Actions. A Server Action is a simple async function that runs exclusively on the server, but can be imported and executed directly from a Client Component.

Under the hood, Next.js handles the network serialization automatically via a hidden POST request. This means you do not need to set up a tRPC router, configure React Query, or write traditional API route handlers (/api/users).

Next.js Server Action Implementation
// 1. Server Side Action (actions/userActions.ts)
"use server";

import db from '@/lib/db';
import { revalidatePath } from 'next/cache';

export async function createUser(formData: FormData) {
  const name = formData.get("name") as string;
  const email = formData.get("email") as string;
  
  await db.user.create({ data: { name, email } });
  
  // Automatically purges the cache and updates the UI without a page reload
  revalidatePath("/users"); 
}

// 2. Client Side Execution (components/CreateUser.tsx)
import { createUser } from '@/actions/userActions';

export function CreateUserForm() {
  return (
    {/* Progressive Enhancement: Works even if JavaScript is disabled */}
    <form action={createUser}>
      <input name="name" type="text" />
      <input name="email" type="email" />
      <button type="submit">Save User</button>
    </form>
  );
}
Architectural Insight: Progressive Enhancement

A massive advantage of Server Actions over tRPC is Progressive Enhancement. Because Server Actions tie natively into the HTML <form action> attribute, a user can submit data even before the client-side JavaScript bundle has finished loading, or if JS fails entirely.

3. The Verdict: When to use Which?

Feature tRPC Server Actions
Framework Lock-in Low (Works with Express, React Native) High (Strictly Next.js / React 19)
Boilerplate Code Moderate (Requires Provider & Routers) Near Zero
Cache Revalidation Requires React Query invalidation logic Native (revalidatePath / revalidateTag)

Conclusion

If you are building an ecosystem where multiple clients (like a Next.js web app and an Expo React Native mobile app) need to share the exact same backend logic and TypeScript types, tRPC is the absolute winner. It decouples your API logic from your UI framework.

However, if you are building an exclusive Next.js web application (like a SaaS dashboard or an admin panel), Server Actions represent the pinnacle of developer velocity. By completely bypassing the API layer, Server Actions reduce your codebase size, eliminate React Query complexity, and provide native cache invalidation out of the box.

#Next.js#tRPC#Server Actions#TypeScript#API Design#Web Architecture
Md Nazmus Shakib
Written By

Md Nazmus Shakib

MERN Stack Developer

Specializing in the MERN stack and modern frameworks to engineer secure, SEO-optimized, and scalable digital solutions for visionary brands.

More about the author →