---
title: "How would you design an IndexedDB schema for a multi-user offline application (eg. note-taking app)?"  
description: "How would you design an IndexedDB schema for a multi-user offline application (eg. note-taking app)?"  
author: "Ponu Maurya"  
published: 2025-07-06  
updated: 2025-07-06  
canonical: https://www.mindstick.com/interview/34319/how-would-you-design-an-indexeddb-schema-for-a-multi-user-offline-application-eg-note-taking-app  
category: "database"  
tags: ["database", "indexeddb"]  
reading_time: 5 minutes  

---

# How would you design an IndexedDB schema for a multi-user offline application (eg. note-taking app)?

[Designing an IndexedDB schema](https://www.mindstick.com/interview/34304/how-do-you-create-and-open-a-database-in-indexeddb) for a [**multi-user offline**](https://www.mindstick.com/interview/34298/how-do-you-handle-offline-data-sync-using-indexeddb) **note-taking app** requires a structure that supports:

- Multiple users
- Multiple notes per user
- Sync and status tracking
- Efficient querying (e.g., by user, tags, sync state)

## Recommended Object Store Schema

We’ll define **three object stores**:

### 1. `users` – Stores basic user info

```javascript
{
  "id": "user123",
  "name": "Alice",
  "email": "alice@example.com"
}
```

### 2. `notes` – Stores each note

```javascript
{
  "id": "note456",
  "userId": "user123",          // Foreign key to users
  "title": "Shopping List",
  "content": "Milk, Eggs, Bread",
  "createdAt": 1725138000000,
  "updatedAt": 1725139000000,
  "synced": false,
  "tags": ["shopping", "todo"]
}
```

### 3. `tags` (optional) – For global tagging/filters

```javascript
{
  "name": "shopping",
  "color": "#FFD700"
}
```

## Object Store Design

| Store Name | Key Path | Indexes | Purpose |
| --- | --- | --- | --- |
| `users` | `id` | `email` (unique) | Auth, ownership |
| `notes` | `id` | `userId`, `updatedAt`, `synced` | Note lookup, syncing, sorting |
| `tags` | `name` | none | Optional visual tagging |

## Schema Setup (in `onupgradeneeded`)

```javascript
const db = event.target.result;

// users
const userStore = db.createObjectStore("users", { keyPath: "id" });
userStore.createIndex("email", "email", { unique: true });

// notes
const noteStore = db.createObjectStore("notes", { keyPath: "id" });
noteStore.createIndex("userId", "userId");
noteStore.createIndex("updatedAt", "updatedAt");
noteStore.createIndex("synced", "synced");

// tags (optional)
const tagStore = db.createObjectStore("tags", { keyPath: "name" });
```

## Sync Support Example

To support sync with a server:

- Use a `synced` flag (`true/false`)
- Use `updatedAt` timestamp for conflict resolution
- Optionally include `isDeleted` for soft-deletes

## Example Queries

| Query | How to Perform |
| --- | --- |
| Get all notes for user `X` | `notes.index("userId").getAll("user123")` |
| Get unsynced notes | `notes.index("synced").getAll(false)` |
| Get notes updated after a date | Use `IDBKeyRange.lowerBound(timestamp)` |
| Sort notes by update time | Use `updatedAt` index with cursor |

## Extra Considerations

| Feature | Suggestion |
| --- | --- |
| Encryption | Use Web Crypto API for secure note content |
| Data expiration | Add `lastOpenedAt` and prune unused accounts |
| Multi-device sync | Store a `remoteId` or `rev` to map local-to-server sync |
| Conflict resolution | Track `updatedAt`, `userId`, and `deviceId` if needed |

## Final Tip

Wrap all IndexedDB operations in a `Promise`-based helper or use a library like:

- `idb`
- `Dexie.js`

## Answers

### Answer by Ponu Maurya

[Designing an IndexedDB schema](https://www.mindstick.com/interview/34304/how-do-you-create-and-open-a-database-in-indexeddb) for a [**multi-user offline**](https://www.mindstick.com/interview/34298/how-do-you-handle-offline-data-sync-using-indexeddb) **note-taking app** requires a structure that supports:

- Multiple users
- Multiple notes per user
- Sync and status tracking
- Efficient querying (e.g., by user, tags, sync state)

## Recommended Object Store Schema

We’ll define **three object stores**:

### 1. `users` – Stores basic user info

```javascript
{
  "id": "user123",
  "name": "Alice",
  "email": "alice@example.com"
}
```

### 2. `notes` – Stores each note

```javascript
{
  "id": "note456",
  "userId": "user123",          // Foreign key to users
  "title": "Shopping List",
  "content": "Milk, Eggs, Bread",
  "createdAt": 1725138000000,
  "updatedAt": 1725139000000,
  "synced": false,
  "tags": ["shopping", "todo"]
}
```

### 3. `tags` (optional) – For global tagging/filters

```javascript
{
  "name": "shopping",
  "color": "#FFD700"
}
```

## Object Store Design

| Store Name | Key Path | Indexes | Purpose |
| --- | --- | --- | --- |
| `users` | `id` | `email` (unique) | Auth, ownership |
| `notes` | `id` | `userId`, `updatedAt`, `synced` | Note lookup, syncing, sorting |
| `tags` | `name` | none | Optional visual tagging |

## Schema Setup (in `onupgradeneeded`)

```javascript
const db = event.target.result;

// users
const userStore = db.createObjectStore("users", { keyPath: "id" });
userStore.createIndex("email", "email", { unique: true });

// notes
const noteStore = db.createObjectStore("notes", { keyPath: "id" });
noteStore.createIndex("userId", "userId");
noteStore.createIndex("updatedAt", "updatedAt");
noteStore.createIndex("synced", "synced");

// tags (optional)
const tagStore = db.createObjectStore("tags", { keyPath: "name" });
```

## Sync Support Example

To support sync with a server:

- Use a `synced` flag (`true/false`)
- Use `updatedAt` timestamp for conflict resolution
- Optionally include `isDeleted` for soft-deletes

## Example Queries

| Query | How to Perform |
| --- | --- |
| Get all notes for user `X` | `notes.index("userId").getAll("user123")` |
| Get unsynced notes | `notes.index("synced").getAll(false)` |
| Get notes updated after a date | Use `IDBKeyRange.lowerBound(timestamp)` |
| Sort notes by update time | Use `updatedAt` index with cursor |

## Extra Considerations

| Feature | Suggestion |
| --- | --- |
| Encryption | Use Web Crypto API for secure note content |
| Data expiration | Add `lastOpenedAt` and prune unused accounts |
| Multi-device sync | Store a `remoteId` or `rev` to map local-to-server sync |
| Conflict resolution | Track `updatedAt`, `userId`, and `deviceId` if needed |

## Final Tip

Wrap all IndexedDB operations in a `Promise`-based helper or use a library like:

- `idb`
- `Dexie.js`


---

Original Source: https://www.mindstick.com/interview/34319/how-would-you-design-an-indexeddb-schema-for-a-multi-user-offline-application-eg-note-taking-app

Copyright © MindStick Software Pvt. Ltd. This Markdown version is provided for developers, AI systems, and offline reading.
