ποΈ How to Structure Redux for Large-Scale Apps (200+ Screens)
A practical, enterprise-ready Redux architecture guide with real examples.
π Table of Contents
- Why Redux Structure Matters
- Redux Explained with a Simple Analogy
- Goals of a Good Redux Architecture
- Recommended Redux Folder Structure (200+ Screens)
- Why This Structure Works for Enterprise Apps
- Clean Redux Store Setup
- Feature Level Slice Example (Users)
- How Features Stay Self Contained
- Where Should Async API Calls Go?
- Enterprise Redux Rules You Must Follow
- Can a Feature Have Multiple Slices?
- Combining Multiple Slices Inside a Feature
- Final Redux State Shape
- When Should You Split Slices?
- 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
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
}
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/
Clean Redux Store Setup
app/store.js
import { configureStore } from "@reduxjs/toolkit";
import rootReducer from "./rootReducer";
export const store = configureStore({
reducer: rootReducer,
});
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,
});
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;
How Features Stay SelfContained
/features/users
βββ slices/
βββ api/
βββ pages/
βββ components/
βββ index.js
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();
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
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,
});
Final Redux State Shape
{
users: {
list: {},
details: {},
permissions: {},
filters: {}
},
payments: {},
orders: {},
auth: {}
}
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
Git: https://github.com/ZeeshanAli-0704/front-end-system-design
Top comments (0)