26. Pattern: Master Detail
The Master Detail pattern allows clients to efficiently navigate heavy time-series or hierarchical datasets by first querying lightweight summary data for a given date (the “Master” view) and subsequently retrieving high-resolution, intra-day data on demand (the “Detail” view).
Rather than overwhelming the client with massive payloads of granular data that the user may never look at, this pattern enforces a two-step retrieval process. It provides immediate high-level visibility while keeping network traffic, database query times, and memory consumption strictly proportional to user interaction.
26.1. Overview
Dashboards, financial applications, and IoT monitoring systems frequently display historical data over time. When a user looks at a specific date (e.g., September 25, 2026), they typically need an aggregate summary first (total sales, average temperature, end-of-day balance). Only when they select that date do they need the granular intra-day metrics (minute-by-minute temperature fluctuations or individual transactions).
Without a Master Detail separation, APIs often dump thousands of granular records into a single response, leading to sluggish rendering, excessive bandwidth usage, and timeouts.
The Master Detail pattern solves this by dividing the responsibility:
- The Master endpoint (
/sales/daily-summary?date=2026-09-25) returns pre-aggregated, low-resolution data spanning the requested period. - The Detail endpoint (
/sales/2026-09-25/transactionsor/sales?date=2026-09-25&resolution=minute) returns the high-resolution intra-day data explicitly requested by the client.
This design naturally complements the concepts established in Pattern 25: Filter Collection by Identifier. While that pattern resolves the N+1 HTTP Request Problem by fetching specific batches of known IDs, this pattern prevents payload bloat by deferring the fetch of unknown, voluminous child records until they are explicitly needed.
26.2. When to Use Master Detail
Use the Master Detail pattern when:
- Exposing high-frequency time-series data.
- e.g., Fetching daily server CPU load averages, then drilling down into 5-minute intervals for a specific day.
- Handling financial ledgers or transactional logs.
- e.g., Displaying a monthly calendar view of total daily spend, then fetching individual transactions when a user clicks a specific date.
- Supporting user interfaces with progressive disclosure.
- UI paradigms that show summary charts or lists first and require a user action (click/tap) to expand the detailed view.
- Payloads for full detail exceed acceptable performance thresholds.
- If returning the detailed intra-day data pushes the JSON response size into the megabytes, the data must be split into Master and Detail endpoints.
26.3. When NOT to Use Master Detail
Avoid the Master Detail pattern when:
- The dataset is universally small.
- If the detail records for a given date are limited (e.g., maximum 5-10 lightweight records), standard collection fetching is sufficient. Forcing a second network request for trivial amounts of data degrades the user experience.
- Clients require full offline access or bulk processing.
- If the API consumer is an analytical engine or a mobile client designed for offline mode that requires the entire dataset up-front, a bulk export or firehose endpoint is more appropriate.
26.4. What the Pattern Looks Like
Below are HTTP request and response flows demonstrating the progressive retrieval of summary data followed by intra-day details.
1. The Master Request (Summary)
The client requests a high-level summary of a specific date (or date range).
Request
GET /metrics/daily-summary?date=2026-09-25 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOi...
Response
The server returns lightweight aggregated totals for the requested date.
HTTP/1.1 200 OK
Cache-Control: public, max-age=3600
Content-Type: application/json
{
"date": "2026-09-25",
"totalTransactions": 142,
"totalRevenue": 4550.75,
"status": "closed",
"links": {
"detail": "/metrics/2026-09-25/intra-day"
}
}
2. The Detail Request (Intra-day)
After reviewing the summary, the user clicks on the date to view the breakdown. The client follows the detail link to fetch the granular data.
Request
GET /metrics/2026-09-25/intra-day?limit=50 HTTP/1.1
Host: api.example.com
Response
The server returns a paginated list of granular intra-day events.
HTTP/1.1 200 OK
Content-Type: application/json
{
"date": "2026-09-25",
"items": [
{
"id": "txn_8821",
"timestamp": "2026-09-25T08:15:30Z",
"amount": 120.00,
"category": "hardware"
},
{
"id": "txn_8822",
"timestamp": "2026-09-25T09:42:12Z",
"amount": 45.50,
"category": "software"
}
],
"pagination": {
"next_cursor": "e30="
}
}
26.5. Anti-Patterns to Avoid
- Including the detail array by default (Payload Bloat)
- Returning massive nested arrays of detailed logs inside the summary object simply because the client might need them. This exhausts server memory and drastically slows down client parsing.
- Forcing N+1 calls to construct the Master view
- Making the client request all intra-day details just to sum them up on the client side. The server must provide a dedicated Master endpoint with pre-calculated aggregations.
- Inconsistent query parameters between Master and Detail
- If the Master view supports timezone offsets or currency conversions (e.g.,
?tz=America/Denver), the Detail endpoint must accept and respect those exact same parameters to ensure data consistency.
- If the Master view supports timezone offsets or currency conversions (e.g.,
26.6. OpenAPI Example
A complete OpenAPI 3.0.3 specification illustrating the separation of Master (Summary) and Detail (Intra-day) endpoints.
openapi: 3.0.3
info:
title: Metrics API - Master Detail Example
version: 1.0.0
servers:
- url: https://api.example.com
paths:
/metrics/daily-summary:
get:
summary: Retrieve daily summary (Master)
description: Returns pre-aggregated daily metrics for a given date.
tags: [Metrics]
parameters:
- in: query
name: date
required: true
schema:
type: string
format: date
example: "2026-09-25"
responses:
'200':
description: Master summary data
content:
application/json:
schema:
$ref: '#/components/schemas/DailySummary'
/metrics/{date}/intra-day:
get:
summary: Retrieve intra-day details (Detail)
description: Returns granular, high-resolution transaction logs for a specific date.
tags: [Metrics]
parameters:
- in: path
name: date
required: true
schema:
type: string
format: date
example: "2026-09-25"
responses:
'200':
description: Granular detail records
content:
application/json:
schema:
$ref: '#/components/schemas/IntraDayDetail'
components:
schemas:
DailySummary:
type: object
properties:
date:
type: string
format: date
example: "2026-09-25"
totalTransactions:
type: integer
example: 142
totalRevenue:
type: number
format: float
example: 4550.75
links:
type: object
properties:
detail:
type: string
example: "/metrics/2026-09-25/intra-day"
IntraDayDetail:
type: object
properties:
date:
type: string
format: date
items:
type: array
items:
$ref: '#/components/schemas/Transaction'
Transaction:
type: object
properties:
id:
type: string
example: "txn_8821"
timestamp:
type: string
format: date-time
example: "2026-09-25T08:15:30Z"
amount:
type: number
format: float
example: 120.00
26.7. Visualizing Master Detail (Mermaid Diagram)
sequenceDiagram
autonumber
actor User as Client Application
participant API as API Server
participant DB as Database (Aggregations)
participant TSDB as Time-Series DB (Granular)
Note over User,TSDB: Phase 1: Retrieve Master Summary
User->>API: GET /metrics/daily-summary?date=2026-09-25
API->>DB: SELECT SUM(amount), COUNT(id) FROM metrics WHERE date='2026-09-25'
DB-->>API: { totalTransactions: 142, totalRevenue: 4550.75 }
API-->>User: 200 OK (Lightweight Summary)
Note over User: User reviews summary, clicks to view daily breakdown
Note over User,TSDB: Phase 2: Retrieve Intra-Day Detail On-Demand
User->>API: GET /metrics/2026-09-25/intra-day
API->>TSDB: SELECT * FROM transactions WHERE date='2026-09-25' ORDER BY time
TSDB-->>API: List of 142 granular records
API-->>User: 200 OK (Heavy Detail Payload)