The nanoid vs Math.random() vs Date.now() — What's the Best Way to Generate Unique IDs in JavaScript?

Nitin KumarNitin Kumar
3 min read

When you're building features like a to-do list, a chat app, or anything that dynamically creates items, you'll need unique IDs. And it’s tempting to go with what you already know:

const id1 = Math.random();
const id2 = Date.now();

But wait up… is that safe?
Let’s break it down with some real-developer talk — not your 12th-grade physics class 😅.


⚠️ The Problem: Duplicate IDs = Bugs

Imagine your React app rendering a list of tasks, and suddenly... 🔥 two tasks have the same ID.
React freaks out. Your state gets messed up. Users start throwing phones.

Why? Because you trusted Math.random() or Date.now() too much.


🧪 Option 1: Math.random()

const id = Math.random().toString(36).substr(2, 9);

✅ Pros:

  • Super easy to write

  • No imports needed

❌ Cons:

  • Can generate duplicate IDs if called quickly (especially during fast loops or async updates)

  • Not really random — it's pseudo-random

  • Not cryptographically secure


🕒 Option 2: Date.now()

const id = Date.now();

✅ Pros:

  • Gives you a timestamp

  • Always increasing (sort of)

❌ Cons:

  • Only accurate to the millisecond

  • Two IDs generated in the same millisecond = 💥 Collision

  • Still not safe for fast, repeated operations


🔐 Option 3: nanoid (The Rockstar 🤘)

import { nanoid } from '@reduxjs/toolkit';
// or: import { nanoid } from 'nanoid';

const id = nanoid(); // "V1StGXR8_Z5jdHi6B-myT"

✅ Pros:

  • Super low chance of duplicate IDs

  • Fast and tiny

  • Safe even when generating thousands of IDs per second

  • Used by real-world apps like Redux Toolkit, Vite, and more

❌ Cons:

  • You need to install a package (but trust me — it's worth it)
npm install nanoid

📊 Quick Comparison:

MethodCollision RiskEasy to UseSafe for Production?
Math.randomHigh✅ Yes❌ Nope
Date.nowMedium✅ Yes❌ Risky
nanoidVery Low✅ Easy✅ Safe

💡 Real Example in Redux Toolkit

import { createSlice, nanoid } from '@reduxjs/toolkit';

const todosSlice = createSlice({
  name: 'todos',
  initialState: [],
  reducers: {
    addTodo: {
      reducer(state, action) {
        state.push(action.payload);
      },
      prepare(text) {
        return {
          payload: {
            id: nanoid(), // ← unique ID
            text,
            completed: false
          }
        };
      }
    }
  }
});

🎯 Final Thoughts

If you're building anything where IDs must be unique, don’t gamble with Math.random() or Date.now().

Use nanoid() — it’s small, fast, and safe. Just like the best dev tools should be.


0
Subscribe to my newsletter

Read articles from Nitin Kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Nitin Kumar
Nitin Kumar