JSON Server transforms frontend development by providing instant REST APIs from simple JSON files. Whether you're building a React application, testing UI components, or demonstrating a proof-of-concept, JSON Server eliminates backend dependencies and accelerates your workflow.
This guide explains the stable and beta JSON Server interfaces used by the examples below. Check the official JSON Server repository for the current release and query behavior before installing. JSON Server is intended for prototyping, testing, and learning rather than production workloads.
This comprehensive guide walks you through installation, configuration, and best practices to help you choose the right version for your specific development needs.
What is JSON Server?
JSON Server is a Node.js tool that creates a full REST API from a simple JSON file. You provide a JSON file containing your data structure, and it automatically generates endpoints for GET, POST, PUT, PATCH, and DELETE operations. No database configuration, no server code, no complex routing setup.
The tool runs on your local machine or remote server and responds to HTTP requests just like a real API would. This eliminates backend dependencies during frontend development.
Purpose and use cases
Developers use JSON Server for rapid prototyping. When building a React, Vue, or Angular application, you can start developing the frontend interface without waiting for the actual backend to be ready.
Testing UI components in isolation becomes straightforward. Create test data, simulate different scenarios, and verify your frontend logic works correctly before integrating with the real API. This approach supports parallel development and reduces blocking dependencies between teams.
The tool excels at creating demonstrations and proof-of-concepts. Mock up an entire application with realistic data interactions to show clients or stakeholders without investing weeks in backend development.
Version notes and compatibility
Critical: v1.0.0-beta.3 has known issues
Confirmed issues in beta
-
_embedand_expandare documented in the official README but users report they don't work reliably (GitHub issue #1638 opened May 2024, still unresolved). Test thoroughly before relying on these features. - The
--routesflag is not documented in v1 beta (GitHub issues #1512, #1601).
Use v0.17.4 for production-like work. Only use v1 beta if you don't need relational queries, are testing new ID and sorting behaviors, or can switch versions if needed.
This guide covers both versions. Version 0.17.4 remains the production-ready choice with proven stability. Version 1.0.0-beta.3 remains in beta with documented features that don't work reliably.
Fair Source License: Organizations with three or more users should sponsor the project to support sustainable development.
Version comparison
| Review area | Legacy v0.17 documentation | Current v1 documentation |
|---|---|---|
| Release identity | Pin the exact legacy package version if compatibility is required | Check the official repository and release tag before installation |
| Query syntax | Validate pagination, sorting, range, embedding, and expansion against the pinned version | Validate the same behaviors against the installed v1 release |
| Runtime | Use the Node.js range declared by the pinned package | Use the Node.js range declared by the selected release |
| Custom routes | Confirm whether the pinned legacy feature is required | Check the current documentation and migration notes |
| Intended use | Prototyping and compatibility testing | Prototyping, testing, and learning; do not infer production suitability |
| Decision | Keep only for a tested legacy dependency | Prefer a reviewed current release when its behavior matches the test suite |
Note:
v0.17.4 supports multiple pagination approaches: use _limit alone, _page with _limit, or _page with _per_page. v1 requires both _page and _per_page together.
Decision guide
Choose the right version for your needs:
| Your situation | Selection rule |
|---|---|
| Existing legacy fixtures | Pin the known version and add regression tests before changing it |
| New CRUD prototype | Start from a reviewed current release and test every query behavior the prototype needs |
| Routes, embedding, or expansion | Verify the exact installed version against the official documentation and local tests |
| Teaching or learning | State the installed version so examples and expected behavior remain reproducible |
Getting started
Quick start: choose your version first
Option one: stable v0.17.4 (recommended)
Install the stable version that includes working routes and embed functionality:
“`bash title="Install JSON Server 0.17.4 globally" npm install -g json-server@0.17.4
Create your data file. Numeric IDs work perfectly in v0.17.4:
```bash title="Create a JSON database with a numeric ID"
echo '{"posts":[{"id":1,"title":"Hello World"}]}' > db.json
Start the server using the official simple form:
“`bash title="Start JSON Server from db.json" npx json-server db.json
Or with the `--watch` flag for automatic reloading (recommended for development):
```bash title="Start JSON Server with file watching"
npx json-server --watch db.json
Test that relational queries work correctly in this version:
“`bash title="Fetch posts with embedded comments" curl "/posts?_embed=comments"
#### Option two: v1.0.0-beta.3 (testing only)
Run the beta version without permanent installation:
```bash title="Start JSON Server 1.0.0 beta 3"
npx json-server@1.0.0-beta.3 db.json
Create data file with string IDs, which are required in v1 beta:
“`bash title="Create a JSON database with a string ID" echo '{"posts":[{"id":"1","title":"Hello"}]}' > db.json
Start the server. Keep in mind that relational query features are unreliable in this beta version:
```bash title="Start the JSON Server beta with file watching"
npx json-server@1.0.0-beta.3 --watch db.json
Warning: The --routes, _embed, and _expand features have reliability issues in v1.0.0-beta.3. Use v0.17.4 if you need these features.
Installation prerequisites
For v1.0.0-beta.3: Node.js 18.3 or higher is required. For v0.17.4: Node.js 14 or higher is required.
Recommended versions include Node.js 20.x or Node.js 22.x LTS. Node.js 22.x LTS (recommended for new projects) offers the best balance of features and long-term support for new projects.
Long-term support versions provide security patches and stability. npm comes bundled with Node.js and serves as the package manager for installing JSON Server.
Setting up Node.js on Debian 12
Whether you're setting up locally or deploying for team collaboration, start by updating your system packages to ensure everything is current:
“`bash title="Update and upgrade Debian packages" apt update && apt upgrade -y
#### Verify the installation
Install Node.js and npm from NodeSource:
```text title="Show a misplaced Node.js installation instruction"
Install Node.js and npm from the official NodeSource repository to get the latest LTS version with automatic updates:
Then install the packages:
Safety check: A pipe-to-shell installer executes remote content immediately. Review the official NodeSource instructions, download the script separately, inspect it, and verify its origin before running it with administrative privileges.
“`bash title="Install Node.js 22 from NodeSource" curl -fsSL https://deb.nodesource.com/setup_22.x | bash – apt install -y nodejs
For other Linux distributions or installation methods, visit the [NodeSource repository](https://deb.nodesource.com/setup_22.x).
Verify the installation by checking the versions:
```bash title="Show the Node.js and npm versions"
node -v
npm -v
Installing JSON Server
Option 1: global installation
Global installation provides persistent access across all projects.
For stable v0.17.4 (recommended for most users):
“`bash title="Install JSON Server 0.17.4 globally" npm install -g json-server@0.17.4
For testing v1 beta features:
```bash title="Install JSON Server 1.0.0 beta 3 globally"
npm install -g json-server@1.0.0-beta.3
Option 2: one-time use with npx
Run without permanent installation, ideal for occasional use or evaluation:
“`bash title="Run JSON Server 0.17.4 once with npx" npx json-server@0.17.4 db.json
#### Verify installation
Check that JSON Server is available on your system:
```bash title="Show the installed JSON Server version"
json-server --version
Core usage
Creating your first mock API
Create a JSON file with your mock data structure. This file acts as your database and defines what resources your API will serve:
“`json title="Define a posts and comments mock database" { "posts": [ { "id": 1, "title": "Getting Started with JSON Server", "author": "John Doe", "views": 150 } ], "comments": [ { "id": 1, "text": "Great article", "postId": 1 } ] }
Start JSON Server with the simple form:
```bash title="Start JSON Server from db.json"
npx json-server db.json
Or with the --watch flag for automatic reloading when you modify db.json:
“`bash title="Start JSON Server with file watching" npx json-server –watch db.json
Your API now runs at `` with all available routes displayed.
### Understanding CRUD operations
JSON Server automatically creates endpoints for each resource. Retrieve all posts using a GET request:
```bash title="List all posts from the mock API"
curl /posts
Get a specific post by including its ID in the URL:
“`bash title="Fetch post 1 from the mock API" curl /posts/1
Create a new post by sending a POST request with JSON data:
```bash title="Attempt to create a post with curl"
curl -X POST /posts
-H "Content-Type: application/json"
-d '{"title":"New Post","author":"Mike","views":0}'
Update a post completely using PUT or partially using PATCH:
“`bash title="Attempt to update post 1 with curl" curl -X PATCH /posts/1 -H "Content-Type: application/json" -d '{"views":250}'
Delete a post using the DELETE method:
```bash title="Delete post 1 from the mock API"
curl -X DELETE /posts/1
ID handling differences
In version 0.17.4, IDs can be numbers or strings. The server accepts both formats and maintains your choice.
In version 1.0.0-beta.3, IDs are always strings. The server auto-generates string IDs when you omit them during record creation. Even if you provide numeric IDs, they convert to strings.
Example of auto-generated string IDs in v1 beta:
“`bash title="Attempt to create a post with an automatic ID" curl -X POST /posts -H "Content-Type: application/json" -d '{"title":"Auto ID Post","views":0}'
This returns a response with string ID:
```json title="Show a post response with a string ID"
{"id":"2","title":"Auto ID Post","views":0}
Working with query parameters
Sort results by any field using the _sort parameter. In v0.17.4, use _sort with _order:
“`bash title="Sort posts by views descending in version 0.17.4" curl "/posts?sort=views&order=desc"
In v1.0.0-beta.3, you can use comma-separated fields with minus prefix for descending order:
```bash title="Sort by ID ascending and views descending in version 1"
curl "/posts?_sort=id,-views"
Or single field with minus sign for descending order:
“`bash title="Sort posts by views descending in version 1" curl "/posts?_sort=-views"
For ascending order:
```bash title="Sort posts by views ascending"
curl "/posts?_sort=views"
Search across all string fields using the q parameter. This performs case-insensitive searches and matches partial strings:
“`bash title="Search posts for JSON" curl "/posts?q=JSON"
v0.17.4 offers flexible pagination options:
```bash title="Compare three version 0.17.4 pagination requests"
## Option 1: Limit only (first 10 records)
curl "/posts?_limit=10"
## Option 2: Page with limit
curl "/posts?_page=1&_limit=10"
## Option 3: Page with per_page
curl "/posts?_page=1&_per_page=10"
All three approaches work in v0.17.4, giving you flexibility in how you structure pagination requests.
Paginate results in v1 beta using _per_page:
“`bash title="Fetch the first page with ten posts in version 1" curl "/posts?page=1&per_page=10"
Filter results using comparison operators: `_gt` (greater than), `_gte` (greater than or equal), `_lt` (less than), `_lte` (less than or equal), and `_ne` (not equal):
```bash title="Filter posts with 100 to 200 views"
curl "/posts?views_gte=100&views_lte=200"
These pagination methods correspond to the version differences outlined in the comparison table above. Choose the approach that matches your version.
Range selection
Use range parameters to slice results. These work in both v0.17.4 and v1.0.0-beta.3.
Get records 10 through 19:
“`bash title="Fetch records 10 through 19" curl "/posts?start=10&end=20"
Get 10 records starting from index 10:
```bash title="Fetch ten records starting at index 10"
curl "/posts?_start=10&_limit=10"
Working with related data
Version 0.17.4 (reliable)
Relational queries work consistently in v0.17.4. Embed comments in posts:
“`bash title="Embed comments in posts" curl "/posts?_embed=comments"
Expand post in comment:
```bash title="Expand the parent post in each comment"
curl "/comments?_expand=post"
Version 1.0.0-beta.3 workarounds
The official v1 documentation shows _embed and _expand syntax, but multiple users report these features don't work reliably (GitHub issue #1638, opened May 2024, still unresolved).
For v1 beta users who need relational data, use the workaround implementations described below.
Official syntax that may not work:
“`bash title="Try the unreliable beta embed query" curl "/posts?_embed=comments"
Recommended workarounds:
#### Workaround 1: separate requests
Fetch the post:
```bash title="Fetch post 1 separately"
curl /posts/1
Fetch related comments:
“`bash title="Fetch comments for post 1 separately" curl "/comments?postId=1"
Combine in your application code:
```javascript title="Combine a post and its comments in JavaScript"
const post = await fetch('/posts/1').then(r => r.json())
const comments = await fetch(`/comments?postId=${post.id}`).then(r => r.json())
post.comments = comments
Workaround 2: custom middleware
Create custom middleware to manually join data. Save this as embed-middleware.js:
“javascript title="Implement custom embed middleware" // embed-middleware.js const fs = require('fs') module.exports = function(req, res, next) { if (req.query._embed) { const db = JSON.parse(fs.readFileSync('db.json', 'utf8')) const resource = req.path.split('/')[1] const embedResource = req.query._embed let data = db[resource] if (Array.isArray(data)) { data.forEach(item => { item[embedResource] = db[embedResource].filter( sub => sub[${resource.slice(0, -1)}Id`] === item.id ) }) } return res.json(data) } next() }
Load the middleware when starting your server:
```bash title="Start JSON Server with embed middleware"
json-server db.json --middlewares embed-middleware.js
Advanced features
Setting up custom routes
Version 0.17.4 (working)
Custom routes work perfectly in v0.17.4 using the --routes flag. Create a routes configuration file:
“`json title="Map custom JSON Server routes" { "/api/*": "/$1", "/blog/:resource/:id/comments": "/:resource/:id/comments" }
Start JSON Server with the routes file:
```bash title="Start JSON Server with a routes file"
json-server db.json --routes routes.json
Version 1.0.0-beta.3 (not documented)
The --routes flag is not documented in v1.0.0-beta.3 (GitHub issues #1512, #1601). Use custom middleware as a workaround.
Save this as routes-middleware.js:
“`javascript title="Rewrite API-prefixed URLs in middleware" // routes-middleware.js module.exports = function(req, res, next) { if (req.url.startsWith('/api/')) { req.url = req.url.replace('/api/', '/') } next() }
Load the routes middleware when starting your server:
```bash title="Start JSON Server with routes middleware"
json-server db.json --middlewares routes-middleware.js
Implementing middleware
Create middleware files to add custom logic. Middleware functions run before JSON Server processes requests.
Save this as middleware.js:
“javascript title="Log requests and set a custom response header" // middleware.js module.exports = function(req, res, next) { console.log(${req.method} ${req.url}`) res.header('X-Custom-Header', 'Value') next() }
Load middleware when starting the server:
```bash title="Start JSON Server with custom middleware"
json-server db.json --middlewares middleware.js
Serving static files
JSON Server serves static files alongside your API. Create a public directory for static content:
“`bash title="Create a public directory and index page" mkdir public echo 'API Documentation' > public/index.html
Start the server with static file serving enabled:
```bash title="Serve the public directory with JSON Server"
json-server db.json --static ./public
Production considerations
Performance considerations
JSON Server loads the entire database into memory. Small datasets under 1MB provide excellent performance. Medium datasets between 1MB and 10MB offer good performance. Large datasets exceeding 10MB show noticeable slowdown.
For datasets with more than 10,000 records, use pagination for all requests, implement data filtering at the client level, or switch to a real database for testing.
For teams working with large datasets, hosting JSON Server on a remote development server ensures consistent performance across all developers. This eliminates environment-specific issues and provides a shared testing environment.
Security considerations
JSON Server is designed for development environments only. Never expose it to the public internet without additional security measures. Use firewall rules to restrict access.
Allow connections only from specific IP addresses:
“`bash title="Allow one IP address to reach port 3000" sudo ufw allow from 192.168.1.100 to any port 3000
The tool does not support HTTPS by default. For encrypted connections, place it behind nginx.
Example nginx configuration:
```nginx title="Proxy JSON Server over HTTPS with Nginx"
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass ;
proxy_set_header Host $host;
}
}
Common pitfalls to avoid
Version 1.0.0-beta.3 specific
Using the --routes flag: Not documented in v1 beta. Use v0.17.4 or custom middleware.
Expecting _embed to work reliably: Documented but unreliable (GitHub issue #1638). Use v0.17.4 or make separate requests.
Using numeric IDs: IDs must be strings like "1", not numbers, in v1 beta.
General issues
Forgetting the --watch flag: Changes to db.json will not reflect without a server restart.
Exposing to internet without security: JSON Server has no authentication. Use firewall protection.
Large datasets exceeding 10MB: Performance degrades significantly. Use pagination and consider real databases.
Alternatives and decision guide
Alternative tools
Mirage JS runs entirely in the browser and intercepts network requests at the client level, ideal for frontend-only development.
Mockoon offers a desktop application with a graphical interface for developers who prefer visual tools.
WireMock is written in Java and provides advanced stubbing for simulating complex API behaviors.
Postman Mock Server integrates with the Postman ecosystem for teams already using Postman for API testing.
When to use JSON Server
Choose JSON Server for rapid prototyping when you need quick mock APIs for JavaScript projects. Perfect for hackathons, prototypes, and proof-of-concepts where speed matters. The tool works well for small to medium-sized applications during development. Migrate to proper backends with database persistence before production launch. JSON Server excels for teaching and learning. Students can focus on frontend concepts without backend complexity.
Conclusion
JSON Server excels at rapid prototyping when you need quick mock APIs. Choose your version carefully: v0.17.4 offers reliability with all features working correctly, while v1.0.0-beta.3 should only be used if you can work around unreliable relational query features.
For most projects, v0.17.4 remains the safest choice until v1 stabilizes. Start with the Quick Start commands above, test your specific use case, and plan migration to production backends before launch. Remember this is strictly a development tool designed to accelerate prototyping, not replace production infrastructure. The tool's simplicity makes it invaluable during early development stages, but proper backend systems with authentication, data persistence, and scalability should be implemented for production deployments.
Ready to host mock APIs on Virtarix VPS?
Compare VPS sizes for JSON Server, mock APIs, staging endpoints, demos, and development services with root access, NVMe storage, IPv4 + IPv6, snapshots, and backups.
VPS S
For small sites, dev servers and Docker
- ✓ 3 cores
- ✓ 6 GB
- ✓ 50 GB NVMe
- ✓ Unlimited
VPS M
For growing apps, websites and staging
- ✓ 6 cores
- ✓ 16 GB
- ✓ 100 GB NVMe
- ✓ Unlimited