# How JSON Server Handles Relationships Between Collections: The Complete Guide to `_embed`

> Learn how JSON Server handles collection relationships using the _embed query parameter for automatic foreign key resolution and embedded data merging.

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

---

**JSON Server handles relationships between collections by treating them as embedded resources that you request using the `_embed` query parameter, which triggers automatic foreign key resolution and merges related data directly into the response objects.**

JSON Server provides a full fake REST API from a simple JSON file, but real-world applications require modeling relationships between collections. Understanding how JSON Server relationships between collections work is essential for designing clean APIs that handle one-to-many and many-to-one associations without writing custom backend code.

## Understanding the `_embed` Query Parameter for JSON Server Relationships

JSON Server exposes relationships through the **`_embed`** query parameter, a convention introduced in version 1 to replace the earlier `_expand` syntax. When you append `_embed=relatedCollection` to a request, the server intercepts this parameter and triggers the embedding logic that resolves foreign key references.

According to the source code documentation in [`README.md`](https://github.com/typicode/json-server/blob/main/README.md) (lines 258-261), this change to `_embed` makes the API intention explicit: you are embedding child or parent resources directly into the requested entity rather than expanding references.

## How JSON Server Resolves Relationships Under the Hood

The relationship resolution happens across three main components in the codebase: the request parser, the service layer, and the embed helper.

### Parsing the Request in [`src/app.ts`](https://github.com/typicode/json-server/blob/main/src/app.ts)

When a request hits the server, **`parseListParams`** in [`src/app.ts`](https://github.com/typicode/json-server/blob/main/src/app.ts) (lines 64-66) extracts the `_embed` value from the query string. This function parses the comma-separated list of related collections and passes them as an array to the service layer.

### Service Layer Processing in [`src/service.ts`](https://github.com/typicode/json-server/blob/main/src/service.ts)

The **`Service.find`** and **`Service.findById`** methods in [`src/service.ts`](https://github.com/typicode/json-server/blob/main/src/service.ts) (lines 28-32) receive the embed list and iterate over each requested resource. For every relationship, they invoke the internal `embed` helper, passing the parent item, the related collection name, and the database instance.

### The `embed` Helper and Foreign Key Resolution

The core logic resides in the **`embed`** function within [`src/service.ts`](https://github.com/typicode/json-server/blob/main/src/service.ts) (lines 23-47). This function uses the `inflection` library to detect relationship cardinality by checking if the related name is singular or plural:

- **Many-to-one** (singular related name): The function searches the related collection for a record where `id` matches `<related>Id` on the main item. For example, a comment with `postId: 1` embeds the post with `id: 1`.

- **One-to-many** (plural related name): The function gathers all records from the related collection where the foreign key `<parent>Id` equals the main item's `id`. For example, a post with `id: 1` embeds all comments where `postId: 1`.

The resulting related object or array is merged onto the original item under a property named after the related collection, then stored in `res.locals['data']` for final JSON serialization.

## Practical Examples of JSON Server Relationships

### One-to-Many Relationship: Posts and Comments

To fetch posts with their associated comments embedded, use the plural form of the related collection:

```http
GET /posts?_embed=comments

```

JSON Server returns:

```json
[
  {
    "id": "1",
    "title": "Hello World",
    "comments": [
      { "id": "101", "postId": "1", "body": "Great post!" },
      { "id": "102", "postId": "1", "body": "Thanks for sharing." }
    ]
  },
  { "id": "2", "title": "Another Post", "comments": [] }
]

```

### Many-to-One Relationship: Comments and Posts

To fetch a comment with its parent post embedded, use the singular form:

```http
GET /comments?_embed=post

```

Here, JSON Server detects the singular `post`, looks for a `postId` field on the comment, and embeds the matching post record.

### Programmatic API Usage

When using JSON Server as a module, the same embedding logic applies through the service layer:

```javascript
import { Low } from 'lowdb'
import { createApp } from './src/app.js'

const db = await new Low('db.json')
await db.read()
const app = createApp(db)

// Embedding works for both collection queries and single-item lookups
app.get('/posts', (req, res) => { /* _embed handled automatically */ })
app.get('/posts/:id', (req, res) => { /* _embed handled automatically */ })

```

## Summary

- JSON Server handles relationships between collections through the **`_embed`** query parameter, which triggers automatic foreign key resolution.
- The **`parseListParams`** function in [`src/app.ts`](https://github.com/typicode/json-server/blob/main/src/app.ts) extracts embedding instructions from the request.
- The **`embed`** helper in [`src/service.ts`](https://github.com/typicode/json-server/blob/main/src/service.ts) uses the `inflection` library to distinguish between **one-to-many** (plural) and **many-to-one** (singular) relationships.
- Foreign keys follow the convention `<parent>Id` for one-to-many and `<related>Id` for many-to-one associations.
- Embedded data is merged into the response object and stored in `res.locals['data']` before JSON serialization.

## Frequently Asked Questions

### How do I query multiple relationships at once in JSON Server?

You can embed multiple collections by passing a comma-separated list to the `_embed` parameter. For example, `GET /posts?_embed=comments,authors` returns posts with both related comments and author objects merged into each post record. The service layer iterates over each value in the array and resolves the foreign keys independently.

### What is the difference between `_embed` and the old `_expand` parameter?

JSON Server replaced `_expand` with `_embed` in version 1 to make the API more explicit. While `_expand` implied expanding a reference, `_embed` clearly indicates that you are embedding related resources directly into the response object. The underlying functionality remains similar, but `_embed` is the current standard as documented in [`README.md`](https://github.com/typicode/json-server/blob/main/README.md) (lines 258-261).

### How does JSON Server determine if a relationship is one-to-many or many-to-one?

The `embed` function in [`src/service.ts`](https://github.com/typicode/json-server/blob/main/src/service.ts) uses the `inflection` library to check if the requested resource name is singular or plural. A singular name (e.g., `post`) triggers a many-to-one lookup using `<resource>Id` on the parent item. A plural name (e.g., `comments`) triggers a one-to-many lookup using `<parent>Id` on the related items.

### Can I use nested embedding to fetch relationships of relationships?

Standard JSON Server does not support automatic deep embedding through chained `_embed` parameters (e.g., `_embed=comments.author`). You can only embed direct relationships of the requested resource. For nested data, you must make separate requests or customize the database adapter to pre-compute nested structures before JSON Server processes the request.