
In Next.js 15, server-side state management can be handled in a few different ways depending on your use case — especially with the App Router (introduced in Next 13) and React Server Components (RSC) becoming more central.
Here’s a breakdown of how to do server-side state management effectively in Next.js 15:
Server-Side State Management Approaches
1.Using React Server Components (RSC)
Next.js 15 supports Server Components by default in the app/ directory.
You can “manage state” by fetching data on the server and passing it as props to client components (if needed).
This avoids needing global state libraries entirely unless you’re doing complex client-side state interactions.
2.Storing State in Middleware or Cookies (Session-like)
If your “state” is user/session-based, use:
Middleware for request-level logic
Cookies (next/headers or next/response-cookies) for storing server-accessible state
This is great for:
Auth state
User preferences
Locale/language settings
3.API Routes + Database or Cache Layer
For persistent or sharable state, keep it in:
Postgres / MongoDB
Redis / Upstash
Edge config
Then access it via:
When You Do Need Client-Side State (and Bridge It)
You can combine server-side logic with a hydrated client component:
Tools to Help
next/headers, next/response-cookies: Manage request/response state
cache() from React or Next.js: For memoizing server-side data
Zustand or Redux (if you must use client-global state)
TL;DR: Server State in Next.js 15
Use Case
Approach
Data fetched on request
Server Components + fetch
Persisted state (auth, prefs)
Cookies / Middleware
Shared state across components
React Context (server or client)
Client interactivity
Hydrated client components
Heavy state mgmt
Zustand / Redux (client)
Bonus Round
URL query parameters as a form of state management in Next.js 15, in the App Router.
This is actually a super clean and powerful way to manage state — especially when you want the state to be shareable, bookmarkable, and synchronized with navigation (like filters, tabs, pagination, etc.).
In a Server Component
You can access query parameters using the searchParams prop (available in server components):
No client state needed — the URL is the state.
In a Client Component
Use useSearchParams() from next/navigation to read query params reactively:
When should you use this?
Use case
Use query params?
Filters on a page (search, tags)
✅ Yes
Pagination
✅ Yes
Tabs or views
✅ Yes
Auth or sensitive state
❌ No
Transient UI state (hover, drag)
❌ No
Bonus: Deep Linking
This method makes it easy to:
Share filtered views via URLs
Maintain state when the user refreshes
Let users hit “Back” and go to the previous state
Avoid relying on heavy client state management