Skip to main content

Normalisation

Normalisation is the process of organizing data to reduce duplication and improve data integrity.

In frontend state management, it means flattening nested data, storing entities separately, and connecting related entities using unique IDs.

Normalisation = Store each entity once and connect data using IDs

One-line idea: Normalisation = Flatten nested data, store entities separately, and connect them using IDs.

Core Concepts​

Why It Matters​

Frontend applications often receive deeply nested API data.

If the same data is stored in many places, updates become difficult and inconsistent.

Normalisation helps by:

  • removing redundant data
  • improving lookup efficiency
  • simplifying nested relationships
  • storing related data together
  • keeping unrelated data separate
  • making updates easier and safer
Nested data -> harder to update
Normalised data -> easier to update from one place

Core Idea​

Instead of storing full nested objects inside other objects, store each entity separately.

Then use IDs to represent relationships.

Users stored separately
Posts stored separately
Comments stored separately
Tags stored separately

Relations are stored using IDs

This avoids repeating the same object in multiple places.

Basic Normalised Shape​

A common normalised structure uses:

FieldPurpose
byIdsStores records by their unique ID
allIdsStores the list of all entity IDs

Example structure:

users.byIds -> user records by ID
users.allIds -> list of user IDs

This makes direct lookup fast.

state.users.byIds["2"];

The lookup becomes direct because the ID points to the exact record.

Practical Examples​

Example 1: Nested Data​

This is nested data where each user contains posts inside the user object.

const state = {
users: [
{
id: 1,
name: "Alice",
posts: [
{ id: 101, title: "Post 1" },
{ id: 102, title: "Post 2" },
],
},
{
id: 2,
name: "Bob",
posts: [{ id: 103, title: "Post 3" }],
},
],
};

Problem with this shape:

  • posts are nested inside users
  • updating a post requires searching through users
  • relationships are harder to manage
  • duplicated data can appear as app grows

Example 1: Normalised Data​

The normalised version stores users and posts separately.

const state = {
users: {
byIds: {
1: {
id: 1,
name: "Alice",
},
2: {
id: 2,
name: "Bob",
},
},
allIds: [1, 2],
},

posts: {
byIds: {
101: {
id: 101,
title: "Post 1",
userId: 1,
},
102: {
id: 102,
title: "Post 2",
userId: 1,
},
103: {
id: 103,
title: "Post 3",
userId: 2,
},
},
allIds: [101, 103, 102],
},
};

Now users and posts are independent entities.

The relation between user and post is maintained using userId.

What Changed in Example 1​

The normalised structure follows three rules.

1. Store users and posts separately
2. Store relationships using IDs
3. Store entities by ID and maintain allIds list

Direct lookup becomes simple.

state.users.byIds["2"];

This is more efficient than searching through an array of users.

Example 2: More Complex Nested Data​

In larger apps, data can include multiple relationships.

Example:

const state = {
users: [
{
id: 1,
name: "Alice",
posts: [
{
id: 101,
title: "Post 1",
},
],
},
{
id: 2,
name: "Bob",
posts: [
{
id: 102,
title: "Post 2",
},
],
},
],

tags: [
{
id: 301,
name: "Tech",
posts: [{ id: 101 }, { id: 102 }],
},
{
id: 302,
name: "Travel",
posts: [{ id: 102 }],
},
],
};

This kind of nested structure can become difficult to update because users, posts, tags, and comments may all reference each other.

Example 2: Normalised Data​

A better structure stores every entity separately.

const normalized_state = {
users: {
byIds: {
1: {
id: 1,
name: "Alice",
posts: [101],
},
2: {
id: 2,
name: "Bob",
posts: [102],
},
},
allIds: [1, 2],
},

posts: {
byIds: {
101: {
id: 101,
title: "Post 1",
comments: [201],
},
102: {
id: 102,
title: "Post 2",
comments: [202],
},
},
allIds: [101, 102],
},

comments: {
byIds: {
201: {
id: 201,
text: "Comment 1",
},
202: {
id: 202,
text: "Comment 2",
},
},
allIds: [201, 202],
},

tags: {
byIds: {
301: {
id: 301,
name: "Tech",
posts: [101, 102],
},
302: {
id: 302,
name: "Travel",
posts: [102],
},
},
allIds: [301, 302],
},
};

Now each entity has its own collection.

Relationships are represented using arrays of IDs.

What Changed in Example 2​

The normalised version separates:

  • users
  • posts
  • comments
  • tags

Then it stores relationships using IDs.

User -> post IDs
Post -> comment IDs
Tag -> post IDs

This makes it easier to update one post, one comment, or one tag without modifying many nested objects.

Benefits​

Normalisation improves the structure and reliability of application data.

BenefitMeaning
Less duplicationSame data is not stored in many places
Better integrityOne update affects the correct single source
Faster lookupEntity can be accessed directly by ID
Simpler updatesUpdate one object instead of searching nested trees
Cleaner relationshipsRelated data is connected using IDs
Better scalabilityEasier to manage large application state

When to Use​

Use normalisation when the data has many entities and relationships.

Good use cases:

  • users and posts
  • posts and comments
  • products and categories
  • tags and articles
  • dashboards with shared entities
  • frontend stores with repeated API data
  • data that needs frequent updates
Use normalisation when nested data becomes hard to update or duplicate.

When Not to Use​

Normalisation may be unnecessary for very small or simple data.

Avoid overusing it when:

  • the data is small
  • the data is not reused
  • the data has no relationships
  • the data does not need frequent updates
  • nested structure is easier and clear enough
Simple data does not always need normalisation.

Normalisation Table​

AreaExplanation
Main goalReduce redundancy and improve data integrity
Data shapeFlattened entities
RelationshipsStored using IDs
Common structurebyIds and allIds
LookupDirect by ID
Best forRelated entities and large state
Avoid forSmall simple unrelated data

Summary​

Normalisation = Flatten nested data, store entities separately, and connect them using IDs.

Nested data -> duplicate and hard to update
Normalised data -> entities by ID and relationships by IDs

Store once, reference everywhere.