# How to Migrate from JSON Server v0 to v1: Complete Upgrade Guide

> Easily migrate from JSON Server v0 to v1. Learn how to update pagination, relationships, IDs, and CLI flags with this complete upgrade guide.

- Repository: [typicode/json-server](https://github.com/typicode/json-server)
- Tags: migration-guide
- Published: 2026-03-01

---

**JSON Server v1 requires updating pagination parameters from `_limit` to `_per_page`, replacing `_expand` with `_embed` for relationships, removing manual numeric IDs in favor of auto-generated hex strings, and eliminating the `--delay` CLI flag in favor of browser DevTools throttling.**

Upgrading from JSON Server version 0 to version 1 involves several breaking changes that affect how you structure API requests and handle data identification. While the core architecture remains a LowDB wrapper with an Express-like API, the migration impacts ID generation, query parameters, relationship loading, and latency simulation. This guide walks through the specific source code changes in `typicode/json-server` to ensure your client code works seamlessly with v1.

## Breaking Changes in JSON Server v1

### Auto-Generated String IDs Replace Manual Numeric IDs

In [`src/random-id.ts`](https://github.com/typicode/json-server/blob/main/src/random-id.ts), JSON Server v1 implements a new ID generation strategy using Node.js crypto utilities:

```typescript
// src/random-id.ts
import { randomBytes } from 'node:crypto'

export function randomId(): string {
  return randomBytes(2).toString('hex')
}

```

The `Service.create()` method in [`src/service.ts`](https://github.com/typicode/json-server/blob/main/src/service.ts) (lines 45-51) automatically invokes this function when you POST new resources without an ID:

```typescript
async create(name: string, data: Omit<Item, 'id'> = {}): Promise<Item | undefined> {
  const items = this.#get(name)
  if (items === undefined || !Array.isArray(items)) return

  const item = { id: randomId(), ...data }
  items.push(item)
  await this.#db.write()
  return item
}

```

**Migration action:** Remove `id` fields from your POST request bodies. The server now assigns 4-character hexadecimal strings (e.g., `"a3f7"`) automatically, eliminating the need to track numeric sequences client-side.

### Pagination Parameters Renamed from `_limit` to `_per_page`

The pagination logic in [`src/paginate.ts`](https://github.com/typicode/json-server/blob/main/src/paginate.ts) (lines 11-22) no longer recognizes the `_limit` query parameter. Instead, it validates `_per_page` for page sizing:

```typescript
export function paginate<T>(items: T[], page: number, perPage: number): PaginationResult<T> {
  const totalItems = items.length
  const safePerPage = Number.isFinite(perPage) && perPage > 0 ? Math.floor(perPage) : 1
  const pages = Math.max(1, Math.ceil(totalItems / safePerPage))
  // ... calculates prev/next and slices results
}

```

In [`src/service.ts`](https://github.com/typicode/json-server/blob/main/src/service.ts) (lines 38-41), the `find()` method forwards these parameters directly:

```typescript
if (opts.page !== undefined) {
  return paginate(results, opts.page, opts.perPage ?? 10)
}

```

**Migration action:** Update all client requests to use `_per_page` instead of `_limit` when specifying page size, while keeping `_page` for the page number.

### Relationship Embedding Changes from `_expand` to `_embed`

Relationship loading now uses the `_embed` query parameter instead of `_expand`. In [`src/service.ts`](https://github.com/typicode/json-server/blob/main/src/service.ts) (lines 28-34 and 96-104), the service processes embedding through the `embed()` helper function:

```typescript
ensureArray(opts.embed).forEach((related) => {
  results = results.map((item) => embed(this.#db, name, item, related))
})

```

This applies to both collection queries (`find()`) and single resource lookups (`findById()`).

**Migration action:** Replace all instances of `_expand` with `_embed` in your API calls to include nested related resources.

### Removal of the `--delay` CLI Flag

The CLI entry point in [`src/bin.ts`](https://github.com/typicode/json-server/blob/main/src/bin.ts) no longer registers a `--delay` flag for artificial latency. According to the README migration notes, this server-side delay simulation has been removed entirely.

**Migration action:** Remove `--delay` from your startup scripts. Simulate network latency using browser DevTools (Network tab → Throttling) or proxy tools instead of server configuration.

## Code Migration Examples

### Before: JSON Server v0 Patterns

```bash

# Start server

json-server db.json

# Pagination with _limit (v0)

curl "http://localhost:3000/posts?_page=1&_limit=5"

# Expand related comments (v0)

curl "http://localhost:3000/posts/1?_expand=comments"

# POST with manual numeric ID

curl -X POST -H "Content-Type: application/json" \
  -d '{"id":2,"title":"New post"}' \
  http://localhost:3000/posts

```

### After: JSON Server v1 Patterns

```bash

# Start server (command unchanged)

json-server db.json

# Pagination with _per_page (v1)

curl "http://localhost:3000/posts?_page=1&_per_page=5"

# Embed related comments (v1)

curl "http://localhost:3000/posts/1?_embed=comments"

# POST without ID (v1 auto-generates hex string)

curl -X POST -H "Content-Type: application/json" \
  -d '{"title":"New post"}' \
  http://localhost:3000/posts

```

## Summary

- **String IDs:** JSON Server v1 generates hexadecimal string IDs automatically via `randomId()` in [`src/random-id.ts`](https://github.com/typicode/json-server/blob/main/src/random-id.ts); omit the `id` field in POST requests.
- **Pagination syntax:** Replace `_limit` with `_per_page` in query strings, as implemented in [`src/paginate.ts`](https://github.com/typicode/json-server/blob/main/src/paginate.ts).
- **Relationship loading:** Use `_embed` instead of `_expand` to include related data, processed in [`src/service.ts`](https://github.com/typicode/json-server/blob/main/src/service.ts).
- **Delay simulation:** Remove the `--delay` flag from CLI startup commands; use browser DevTools for network throttling instead.

## Frequently Asked Questions

### How do I handle existing numeric IDs when migrating to JSON Server v1?

JSON Server v1 maintains backward compatibility with existing data. If your [`db.json`](https://github.com/typicode/json-server/blob/main/db.json) contains numeric IDs, they remain valid strings (numbers are valid JSON string values). However, all new resources created via POST will receive 4-character hex string IDs generated by the `randomId()` function. Keep existing IDs as-is, but update your client code to expect string IDs for new resources.

### Why was the `_limit` parameter removed in favor of `_per_page`?

The `_per_page` parameter aligns with modern REST API conventions and provides clearer semantic meaning. According to the source code in [`src/paginate.ts`](https://github.com/typicode/json-server/blob/main/src/paginate.ts), the parameter is explicitly validated as `perPage` rather than `limit`, making the API more self-documenting. Update your client libraries to construct URLs with `_per_page` to restore pagination functionality.

### Can I still simulate network delays in JSON Server v1?

No, server-side delay simulation has been removed from the CLI. The [`src/bin.ts`](https://github.com/typicode/json-server/blob/main/src/bin.ts) file no longer parses a `--delay` flag. To test how your application behaves under slow network conditions, use Chrome DevTools Network throttling, Firefox Network Monitor throttling, or tools like Charles Proxy or Clumsy to introduce latency between your client and the JSON Server instance.

### What should I do if my client code expects numeric IDs?

Update your client-side data models to accept strings instead of numbers for the `id` field. Since [`src/service.ts`](https://github.com/typicode/json-server/blob/main/src/service.ts) uses `randomBytes(2).toString('hex')` to generate IDs like `"a3f7"` or `"8b2e"`, any client-side validation expecting integers will fail. TypeScript users should update interfaces from `id: number` to `id: string`, and JavaScript consumers should remove numeric parsing or validation logic.