CLI tool
typicode/json-server avatar
typicode/json-server

json-server v1 beta: a fake REST API from a single db.json

Project brief: Get a full fake REST API with zero coding in less than 30 seconds (seriously).

75,719 stars7,262 forksJavaScriptMIT

At a glance

What is it?
json-server turns one JSON or JSON5 file into a queryable REST API with filtering, sorting, pagination and embedding. The current release is a v1 beta, so the install and the query syntax are worth checking before you commit a team to them.
Who is it for?
Adopt json-server when you need a disposable HTTP endpoint backed by a file you can edit by hand: frontend work against a real fetch call, integration tests, a demo. Do not adopt it as a persistence layer for anything whose data must survive, and do not build on the v1 beta if you need the v0.x query syntax, because _limit and _expand are gone.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem json-server solves, and who hits it

Frontend work stalls when the API is not ready. You either hardcode arrays in the component, or you stand up a small Express app with a handful of routes, and then you maintain that app for the length of the project. json-server collapses that into one file and one command. The README describes the result as a full fake REST API with zero coding, and the shape of the tool matches the claim: you write the data, the server derives the routes.

It is for people who need an HTTP surface, not a database. A React or Angular developer who wants fetch calls to return something real. A test suite that needs a server it can start and stop per run. Someone recording a demo who cannot point at production. The repository's own keywords list reads prototyping, mock, mocking, test, testing, dummy, which is an accurate description of the intended scope.

The scope is also the limit. There is no schema enforcement beyond the optional $schema reference in the README example, no migrations, no concurrency story. If two writers hit the same resource, you are relying on lowdb, which the package.json lists as a dependency and which is a file-backed store. That is fine for a laptop and wrong for a shared environment.

How the routes and query params are derived from db.json

The mechanism is name-based. Each top-level key in the file becomes a route. An array value becomes a full CRUD resource: GET, POST, PUT, PATCH and DELETE on /posts and /posts/:id. An object value becomes a singular resource with GET, PUT and PATCH only, which is why the README lists no DELETE for /profile. There is no route file to edit and no controller to register.

The query layer is where the v1 beta differs most from what older tutorials show. Filtering uses field:operator=value, with operators eq, ne, lt, lte, gt, gte, in, contains, startsWith and endsWith. A bare field with no operator means eq. Nested fields are addressed with dots, so author.name:eq=typicode reaches into an object. Sorting is _sort with a leading minus for descending, and it accepts multiple keys, for example author.name,-views. Pagination is _page with _per_page, and the response is not a bare array: it is an envelope with first, prev, next, last, pages, items and a data array. _per_page defaults to 10. The README states that invalid _page or _per_page values are normalized to valid ranges rather than rejected, which is convenient in a browser and surprising in a test that expects a 400.

Relations are handled by _embed, which inlines related resources, and by the _dependent query param on DELETE, so DELETE /posts/1?_dependent=comments removes the comments that point at that post. For anything the operator list cannot express, _where takes a JSON object and, per the README, overrides normal query params when valid.

Installing json-server and making the first request

The README gives npm as the install path and requires Node 22.12.0 or newer according to the engines field in package.json. Installing it as a dependency is the documented route, and it also puts the json-server binary on your path.

bash
npm install json-server

Next create the data file. The README's example includes a $schema line pointing at the schema shipped in the package, which gives editor completion if your editor reads it.

json
{
  "$schema": "./node_modules/json-server/schema.json",
  "posts": [
    { "id": "1", "title": "a title", "views": 100 },
    { "id": "2", "title": "another title", "views": 200 }
  ],
  "comments": [
    { "id": "1", "text": "a comment about post 1", "postId": "1" }
  ],
  "profile": { "name": "typicode" }
}

Start it. The README shows npx, which works without a local install, and states the server listens on port 3000 and prints a banner reading JSON Server started on PORT :3000 followed by the URL.

bash
npx json-server db.json

Then fetch one record. The README's example request and the response it documents are below; if you see that object, the file was parsed and the route was mounted.

bash
curl http://localhost:3000/posts/1
json
{
  "id": "1",
  "title": "a title",
  "views": 100
}

Run json-server --help for the option list, which the README points at instead of enumerating flags. Static files come from ./public automatically, and additional directories are added by repeating -s, as in json-server db.json -s ./static -s ./node_modules. A db.json5 file is also accepted, using the JSON5 format the README links to.

The v0 to v1 migration is the real cost of adoption

Most json-server material on the web describes v0.x, and the v1 beta changes the query surface in ways that break those examples silently. The README's migration notes list three: id is always a string and is auto-generated when missing, so numeric ids you wrote by hand come back as strings; _limit is deprecated in favour of _per_page alongside _page; and _expand is replaced by _embed for including related resources.

That last one matters because _expand and _embed were never the same operation. _expand pulled the parent into a child response, _embed pushes children into a parent response. A request written as GET /comments?_expand=post has no equivalent spelled the same way in v1. If your fixtures or your frontend client encode those params, the upgrade is a code change, not a version bump.

The README also says the beta documentation is for a version that is usable but should expect breaking changes, and links to the v0.17.4 tree for the stable version. Take that at face value. Pinning to the beta means accepting that the query syntax can move again. There is also no documented rollback procedure, and the README does not describe how to export data back out of the server, so the file you started with remains the only copy you control.

Where a file-backed mock server stops being the right tool

The failure mode is concurrency and durability, and it is structural rather than a bug. The server reads and writes a file through lowdb. Writes go to that file. There is no documented transaction boundary, no locking story and no backup mechanism in the README. Two processes pointed at the same db.json, or a CI job and a developer on a shared mount, is outside what the tool was built for.

Second, the query language is not a query language. _where accepts a JSON object and is the escape hatch, but the operator set is a fixed list of ten comparisons plus string matching. No aggregation, no joins beyond the naming convention that a child carries a parentId field, no full-text search. The moment you need a sum or a group-by, you are writing it in the client or moving off the tool.

Third, the request delay feature that older versions exposed is not in the v1 query list. The truncated migration notes point at browser DevTools instead, so if your workflow depended on simulating a slow network from the server side, that is a thing to verify against json-server --help before you plan around it.

Alternatives and the actual difference in approach

The closest thing to a like-for-like alternative is Mock Service Worker, and the difference is where the interception happens. MSW runs in the browser or in Node and intercepts requests at the network layer, so your application code makes a real fetch and no server process exists. json-server is an actual HTTP server on a port. That distinction decides most choices: MSW fits a test suite or a deployed static demo because there is nothing to host, while json-server fits the case where a second machine, a curl command or a tool outside the browser needs to reach the same endpoint.

Against a hand-written Express app, json-server trades control for setup time. Express gives you middleware, auth and custom routes; json-server gives you a route per key and a fixed operator set. If your mock needs a login flow, json-server has no built-in answer for it, and the search interest in json-server auth reflects that gap rather than a feature.

Against a real backend with a seeded database, the comparison is not close and should not be. json-server's advantage is that the data definition and the API definition are the same file. That is worth a lot during a two-week prototype and worth nothing once the data outlives the prototype.

Licence, maintenance and what the beta cadence implies

The licence is MIT, per both the repository metadata and the license field in package.json. MIT permits commercial use, modification and redistribution provided the copyright notice and permission notice are kept. That is the plain reading of the identifier; specific obligations in your distribution model are a question for your own counsel, not something this article can settle.

On maintenance, the facts are narrow. The repository is not archived, and the last push was on 2026-03-23. The three most recent releases are v1.0.0-beta.13 on 2026-03-13, v1.0.0-beta.14 on 2026-03-20 and v1.0.0-beta.15 on 2026-03-23. Those dates cluster tightly, which is what a beta cadence looks like: small, frequent, breaking. There has been no stable v1 tag, and the README still points readers at v0.17.4 for the stable version.

The upgrade cost follows from that. If you pin the beta, budget for reading the migration notes on each bump, because the query params are the part that moves. If you pin v0.17.4, budget for being on a documented-as-stable but older surface whose examples no longer match the current README.

Editorial conclusion

Adopt json-server when you need a disposable HTTP endpoint backed by a file you can edit by hand: frontend work against a real fetch call, integration tests, a demo. Do not adopt it as a persistence layer for anything whose data must survive, and do not build on the v1 beta if you need the v0.x query syntax, because _limit and _expand are gone. Before writing it into a project, run npx json-server db.json, confirm the port and the startup banner, then check GET /posts/1, GET /posts?views:gt=100 and GET /posts?_embed=comments against your own file. The condition operators and the pagination envelope are the two things most likely to differ from what you expected.

Frequently asked questions

What is json-server?

It is a Node package that serves a REST API from a JSON or JSON5 file. Each top-level key in the file becomes a route, and the README describes the result as a full fake REST API with zero coding.

How do I run json-server?

Create a db.json file, then run npx json-server db.json. The README states the server starts at http://localhost:3000 and prints a banner reading JSON Server started on PORT :3000.

How do I install json-server?

The README gives npm install json-server as the install command, which also provides the json-server binary. The engines field in package.json requires Node 22.12.0 or newer.

How do I use json-server with React or Angular?

There is no framework-specific integration in the README. You start the server on port 3000 and point your application's fetch calls at the routes derived from your db.json keys, such as GET /posts.

How do I use json-server in JavaScript?

The README documents no JavaScript client library. You start the server and call its HTTP routes from your own code, for example a fetch to http://localhost:3000/posts/1.

What is JSON used for?

In json-server the JSON file is the database: top-level keys become routes and array values become CRUD resources. The README also accepts JSON5, which allows unquoted keys and trailing commas.

Official sources

  1. Official README
  2. Project repository
  3. Release notes
For maintainers

Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/typicode-json-server.svg)](https://hysenlabs.com/projects/typicode-json-server)
Community notes

Community notes