DEV Community

Cover image for Frontend System Design: How do you structure Redux for a 200+ screen enterprise application?
ZeeshanAli-0704
ZeeshanAli-0704

Posted on • Edited on

Frontend System Design: How do you structure Redux for a 200+ screen enterprise application?

πŸ—οΈ How to Structure Redux for Large-Scale Apps (200+ Screens)

A practical, enterprise-ready Redux architecture guide with real examples.


πŸ“Œ Table of Contents

  1. Why Redux Structure Matters
  2. Redux Explained with a Simple Analogy
  3. Goals of a Good Redux Architecture
  4. Recommended Redux Folder Structure (200+ Screens)
  5. Why This Structure Works for Enterprise Apps
  6. Clean Redux Store Setup
  7. Feature Level Slice Example (Users)
  8. How Features Stay Self Contained
  9. Where Should Async API Calls Go?
  10. Enterprise Redux Rules You Must Follow
  11. Can a Feature Have Multiple Slices?
  12. Combining Multiple Slices Inside a Feature
  13. Final Redux State Shape
  14. When Should You Split Slices?
  15. Final Summary

Why Redux Structure Matters

When your app grows to 100–200+ screens, Redux can either:

  • βœ… Become your biggest productivity booster
  • ❌ Or turn into an unmaintainable mess

Bad Redux structure leads to:

  • Huge reducers
  • Tight coupling between features
  • Difficult debugging
  • Fear of adding new screens

A good structure, on the other hand, makes your app:

  • Easy to scale
  • Easy to debug
  • Easy to onboard new developers

Redux Explained with a Simple Analogy

Think of your application as a big office building.

  • 🏒 Building β†’ Your application
  • πŸ§‘β€πŸ’Ό Building Manager β†’ Redux Store
  • 🏬 Each Floor β†’ A large feature (Users, Payments, Orders)
  • πŸšͺ Each Room β†’ A screen/page
  • πŸ—„οΈ File Cabinets β†’ Redux slices

The Golden Rule

Files from one floor NEVER mix with another floor.

Each feature manages its own data.
The store only connects features β€” it doesn’t control their internal logic.


Goals of a Good Redux Architecture

A solid Redux setup should:

  • 🎯 Make feature state easy to find
  • 🐞 Make bugs easy to trace
  • πŸš€ Allow easy scaling
  • ♻️ Encourage reuse of shared logic
  • 🧠 Keep mental overhead low

Recommended Redux Folder Structure (200+ Screens)

/src
 β”œβ”€β”€ app/
 β”‚    β”œβ”€β”€ store.js
 β”‚    └── rootReducer.js
 β”‚
 β”œβ”€β”€ features/
 β”‚    β”œβ”€β”€ users/
 β”‚    β”‚    β”œβ”€β”€ api/
 β”‚    β”‚    β”‚   └── usersApi.js
 β”‚    β”‚    β”œβ”€β”€ components/
 β”‚    β”‚    β”‚   └── UserTable.jsx
 β”‚    β”‚    β”œβ”€β”€ pages/
 β”‚    β”‚    β”‚   └── UserListPage.jsx
 β”‚    β”‚    β”œβ”€β”€ slices/
 β”‚    β”‚    β”‚   └── usersSlice.js
 β”‚    β”‚    └── index.js
 β”‚    β”‚
 β”‚    β”œβ”€β”€ payments/
 β”‚    β”œβ”€β”€ orders/
 β”‚    β”œβ”€β”€ dashboard/
 β”‚    └── ...
 β”‚
 β”œβ”€β”€ shared/
 β”‚    β”œβ”€β”€ slices/
 β”‚    β”‚    β”œβ”€β”€ authSlice.js
 β”‚    β”‚    β”œβ”€β”€ uiSlice.js
 β”‚    β”‚    └── appConfigSlice.js
 β”‚    β”œβ”€β”€ hooks/
 β”‚    └── utils/
 β”‚
 β”œβ”€β”€ components/   // truly reusable UI
 └── index.js
Enter fullscreen mode Exit fullscreen mode

Why This Structure Works for Enterprise Apps

βœ” Feature Isolation

Each feature contains everything it needs:

  • slices
  • pages
  • components
  • API logic

Deleting or moving a feature becomes trivial.


βœ” Clean Store

The store stays simple and readable:

{
  users,
  payments,
  orders,
  auth,
  ui
}
Enter fullscreen mode Exit fullscreen mode

No feature knows about another feature’s internals.


βœ” Shared Logic Lives in /shared

Only truly global concerns go here:

  • authentication
  • global loaders
  • modals
  • app configuration

βœ” Infinite Scalability

Adding a new feature never breaks existing ones:

features/newFeature/
  β”œβ”€β”€ slices/
  β”œβ”€β”€ pages/
  β”œβ”€β”€ components/
  └── api/
Enter fullscreen mode Exit fullscreen mode

Clean Redux Store Setup

app/store.js

import { configureStore } from "@reduxjs/toolkit";
import rootReducer from "./rootReducer";

export const store = configureStore({
  reducer: rootReducer,
});
Enter fullscreen mode Exit fullscreen mode

app/rootReducer.js

import { combineReducers } from "@reduxjs/toolkit";

import usersReducer from "../features/users";
import paymentReducer from "../features/payments";
import orderReducer from "../features/orders";

import authReducer from "../shared/slices/authSlice";
import uiReducer from "../shared/slices/uiSlice";

export default combineReducers({
  users: usersReducer,
  payments: paymentReducer,
  orders: orderReducer,
  auth: authReducer,
  ui: uiReducer,
});
Enter fullscreen mode Exit fullscreen mode

Feature Level Slice Example (Users)

import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  list: [],
  loading: false,
};

const usersSlice = createSlice({
  name: "users",
  initialState,
  reducers: {
    setUsers(state, action) {
      state.list = action.payload;
    },
    setLoading(state, action) {
      state.loading = action.payload;
    },
  },
});

export const { setUsers, setLoading } = usersSlice.actions;
export default usersSlice.reducer;
Enter fullscreen mode Exit fullscreen mode

How Features Stay SelfContained

/features/users
 β”œβ”€β”€ slices/
 β”œβ”€β”€ api/
 β”œβ”€β”€ pages/
 β”œβ”€β”€ components/
 └── index.js
Enter fullscreen mode Exit fullscreen mode

Each feature behaves like a mini-application.


Where Should Async API Calls Go?

Option A: createAsyncThunk

βœ” Centralized loading/error handling
βœ” Good for enterprise workflows

Option B: RTK Query

βœ” Caching
βœ” Auto refetch
βœ” Best for data-heavy apps

Option C: Custom Hooks

βœ” Complex business rules
βœ” Highly customized behavior


Enterprise Redux Rules You Must Follow

RULE 1: Never create one giant slice

One feature = one domain.


RULE 2: Pages never talk to Redux directly

const users = useSelector(state => state.users.list);
const dispatch = useDispatch();
Enter fullscreen mode Exit fullscreen mode

RULE 3: Keep shared state minimal

Only:

  • auth
  • modals
  • loaders
  • notifications

RULE 4: Always use createSlice

Less boilerplate. Fewer bugs.


RULE 5: Features must stay isolated

No cross-feature imports.


Can a Feature Have Multiple Slices?

βœ… YES β€” and it SHOULD for large features


Combining Multiple Slices Inside a Feature

src/features/users/slices/
 β”œβ”€β”€ usersListSlice.js
 β”œβ”€β”€ userDetailsSlice.js
 β”œβ”€β”€ userPermissionsSlice.js
 └── userFiltersSlice.js
Enter fullscreen mode Exit fullscreen mode

Combine them in features/users/index.js

import { combineReducers } from "@reduxjs/toolkit";

import list from "./slices/usersListSlice";
import details from "./slices/userDetailsSlice";
import permissions from "./slices/userPermissionsSlice";
import filters from "./slices/userFiltersSlice";

export default combineReducers({
  list,
  details,
  permissions,
  filters,
});
Enter fullscreen mode Exit fullscreen mode

Final Redux State Shape

{
  users: {
    list: {},
    details: {},
    permissions: {},
    filters: {}
  },
  payments: {},
  orders: {},
  auth: {}
}
Enter fullscreen mode Exit fullscreen mode

Clean. Predictable. Scalable.


When Should You Split Slices?

Split when:

  • Slice exceeds 300–400 lines
  • Slice manages multiple screens
  • Slice mixes UI + domain logic
Slice Name Responsibility
usersList table, pagination
filters search, sorting
details profile page
permissions roles & access

Final Summary

πŸ† Best Redux Structure for Large Apps

  • app/ β†’ store & root reducer
  • features/ β†’ one folder per domain
  • shared/ β†’ truly global state
  • multiple slices per feature if needed
  • combine slices inside the feature

🎯 Result

  • Easy to scale
  • Easy to debug
  • Easy to onboard developers
  • Enterprise-ready architecture

More Details:

Get all articles related to system design
Hastag: SystemDesignWithZeeshanAli

systemdesignwithzeeshanali

Git: https://github.com/ZeeshanAli-0704/front-end-system-design

Top comments (0)