Skip to content

Commit adff4e6

Browse files
sarahxsandersbenjieyaacovCR
authored
docs: move migrate from express graphql guide to graphqlJS docs (#4433)
Resolves this feedback: graphql/graphql.github.io#2005 (review) Moving Migrate from express graphQL guide to graphQL-js --------- Co-authored-by: Benjie <benjie@jemjie.com> Co-authored-by: Yaacov Rydzinski <yaacovCR@gmail.com>
1 parent 7569989 commit adff4e6

File tree

3 files changed

+218
-0
lines changed

3 files changed

+218
-0
lines changed

cspell.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ overrides:
4141
- Graphile
4242
- precompiled
4343
- debuggable
44+
- dataloaders
4445

4546
ignoreRegExpList:
4647
- u\{[0-9a-f]{1,8}\}

website/pages/docs/_meta.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const meta = {
66
},
77
'getting-started': '',
88
'running-an-express-graphql-server': '',
9+
'migrating-from-express-graphql': '',
910
'graphql-clients': '',
1011
'authentication-and-express-middleware': '',
1112
'-- 2': {
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
---
2+
title: Migrate from Express GraphQL to GraphQL over HTTP
3+
sidebarTitle: Migrate from Express GraphQL
4+
---
5+
6+
# Migrate from Express GraphQL to GraphQL over HTTP
7+
8+
When GraphQL was open-sourced in 2015, `express-graphql` quickly became the standard way to run a GraphQL server in Node.js.
9+
Built as middleware for Express, it offered a simple and reliable development experience. However, it hasn’t received a
10+
feature update since 2018 and is no longer actively maintained. For modern applications, it lacks support for new transport
11+
features, fine-grained request handling, and deployment flexibility.
12+
13+
[`graphql-http`](https://github.com/graphql/graphql-http) is a lightweight implementation of
14+
the [GraphQL over HTTP specification](https://graphql.github.io/graphql-over-http/draft/). It's framework-agnostic, built to be
15+
composable, and easy to integrate into different server environments. Unlike `express-graphql`, it can run in a wide range of
16+
environments, not just Express.
17+
18+
This guide is for developers currently using `express-graphql` who want to
19+
modernize their stack, adopt the HTTP spec, or decouple their GraphQL server
20+
from Express.
21+
22+
## Benefits of migrating
23+
24+
### `express-graphql` is no longer supported
25+
26+
The library has not received updates for some time. As a deprecated package, it is not evolving with the GraphQL ecosystem. This makes it less flexible for long-term projects.
27+
28+
### `graphql-http` is spec-compliant by default
29+
30+
The GraphQL over HTTP specification defines how GraphQL should be transported over HTTP, including request methods, status codes, content types, and more. `graphql-http` follows this spec precisely, helping your server behave predictably and remain compatible with future tooling.
31+
32+
### It's framework-agnostic by design
33+
34+
Instead of relying on Express, `graphql-http` is built on the standard Web `Request` and `Response` interfaces. It works with Express, Fastify, Node's native HTTP server, and can also be used in serverless and edge environments.
35+
36+
### It fits into modern JavaScript stacks
37+
38+
`graphql-http` supports ESM and works well with modern build tools and lightweight deployment platforms. Its composable design makes it easy to customize, wrap, and integrate into different application architectures.
39+
40+
### Designed for future compatibility
41+
42+
As GraphQL evolves, tools and platforms increasingly expect spec-compliant behavior. Migration to `graphql-http` helps ensure your
43+
server will support future capabilities without relying on workarounds.
44+
45+
### Understand current limitations
46+
47+
Although `graphql-http` is a strong foundation for modern GraphQL servers, it's important to note what it doesn't include:
48+
49+
- It doesn't support subscriptions or experimental features like incremental delivery (`@defer` / `@stream`) out of the box.
50+
- These limitations are by design. `graphql-http` strictly adheres to the current
51+
[GraphQL over HTTP specification](https://graphql.github.io/graphql-over-http/draft/), which does
52+
not yet define behavior for those features.
53+
- If your application needs support for subscriptions or live queries, consider using complementary libraries like
54+
[`graphql-ws`](https://github.com/enisdenjo/graphql-ws) or [`graphql-sse`](https://github.com/enisdenjo/graphql-sse).
55+
56+
These are not limitations unique to `graphql-http`. `express-graphql` does not support these features either, but it's important
57+
to set the right expectations about extensibility.
58+
59+
## Migration guide
60+
61+
The following steps walk through how to migrate an existing `express-graphql` server to use `graphql-http`. The steps assume you already have a working Express app using `express-graphql`.
62+
63+
### Prerequisites
64+
65+
Before you begin, make sure you have:
66+
67+
- Node.js 16 or later
68+
- A GraphQL schema
69+
- An existing Express app configured with `express-graphql`
70+
71+
### Step 1: Install graphql-http and the Express adapter
72+
73+
Install the core `graphql-http` package along with its Express adapter:
74+
75+
```bash
76+
npm install graphql graphql-http
77+
```
78+
79+
The `graphql` package is a peer dependency of `graphql-http`, and must be installed if it isn't already.
80+
81+
### Step 2: Remove express-graphql middleware
82+
83+
In your Express server file, remove the `express-graphql` middleware:
84+
85+
```js
86+
// Before (using express-graphql)
87+
import { graphqlHTTP } from 'express-graphql';
88+
89+
app.use('/graphql', graphqlHTTP({
90+
schema,
91+
graphiql: true,
92+
}));
93+
```
94+
95+
### Step 3: Add graphql-http middleware with createHandler
96+
97+
Replace it with the `graphql-http` handler using the Express adapter:
98+
99+
```js
100+
import express from 'express';
101+
import { createHandler } from 'graphql-http/lib/use/express';
102+
import { schema } from './schema.js';
103+
104+
const app = express();
105+
106+
app.all('/graphql', createHandler({ schema }));
107+
108+
app.listen(4000);
109+
```
110+
111+
- Use `app.all()` to allow both `GET` and `POST` requests.
112+
- The handler accepts an options object for GraphQL-specific settings like `schema`,
113+
`rootValue`, and `context`, but doesn’t handle server-level features such as middleware
114+
or request preprocessing like `express-graphql` did.
115+
116+
### Step 4: Handle context, error formatting, and extensions
117+
118+
You can provide options like `context`, `rootValue`, and `formatError`:
119+
120+
```js
121+
import { GraphQLError } from 'graphql';
122+
123+
app.all('/graphql', createHandler({
124+
schema,
125+
context: async (req, res) => {
126+
const user = await authenticate(req);
127+
return { user };
128+
},
129+
formatError: (error) =>
130+
new GraphQLError(error.message, {
131+
nodes: error.nodes,
132+
path: error.path,
133+
extensions: {
134+
code: 'INTERNAL_SERVER_ERROR',
135+
timestamp: Date.now(),
136+
},
137+
}),
138+
}));
139+
```
140+
141+
- `context` can be a static object or an async function.
142+
- You can also pass `rootValue` or other GraphQL-specific options.
143+
- To modify the HTTP response, such as adding headers or extensions, you’ll need
144+
to do that outside of graphql-http, using Express middleware or route handlers.
145+
146+
### Step 5: Add a GraphQL IDE
147+
148+
Unlike `express-graphql`, `graphql-http` does not include a built-in GraphQL IDE. If you want to add one:
149+
150+
- Use a tool like [Ruru](https://www.npmjs.com/package/ruru) to serve an interactive GraphQL UI locally:
151+
152+
```bash
153+
npx ruru -SP -p 4001 -e http://localhost:4000/graphql
154+
```
155+
156+
- Or serve a static HTML page that embeds [GraphiQL](https://github.com/graphql/graphiql) from a CDN.
157+
158+
In either case, make sure to restrict access in production environments.
159+
160+
### Step 6: Test your setup
161+
162+
After migrating, verify that your server responds correctly:
163+
164+
- Send queries and mutations using your preferred client.
165+
- Check for proper HTTP status codes and response shapes.
166+
- Check the GraphQL `context` and related variables are populated correctly and
167+
that your dataloaders and authorization logic are functioning as expected.
168+
169+
## Best practices
170+
171+
When migrating from `express-graphql` to `graphql-http`, there are a few key differences and potential pitfalls to keep in mind. These tips can help you avoid common issues and ensure a smoother transition.
172+
173+
### Be aware of different error behavior
174+
175+
`graphql-http` follows the GraphQL over HTTP spec closely, which means error formatting and status codes may differ from what you're used to with `express-graphql`. For example:
176+
177+
- Invalid queries may return a `400 Bad Request` instead of a `200 OK`.
178+
- Errors in parsing or validation are surfaced earlier and more strictly.
179+
- You can customize error output using the `formatError` option, but it must conform to the spec.
180+
181+
This can affect client expectations if they were relying on `express-graphql`'s more lenient defaults.
182+
183+
### Watch for framework-specific middleware behavior
184+
185+
Since `graphql-http` is framework-agnostic, it does not handle things like body parsing, CORS, or compression. You'll need to ensure those are handled appropriately by your Express setup:
186+
187+
```js
188+
import cors from 'cors';
189+
import express from 'express';
190+
191+
app.use(cors());
192+
app.use(express.json());
193+
```
194+
195+
This gives you more control but requires a bit more setup.
196+
197+
### Understand streaming and file upload limitations
198+
199+
`graphql-http` aims to support the GraphQL over HTTP spec, including eventually supporting response streaming. However,
200+
support for features like `@defer` and `@stream` is still evolving. These capabilities are experimental in `graphql-js`
201+
and not yet supported by `graphql-http`.
202+
203+
- Some GraphQL clients have begun adding support for multipart responses, but broad adoption is still evolving.
204+
- `graphql-http` does not support streaming features such as `@defer` or `@stream`, as these are not part of the
205+
current GraphQL over HTTP specification.
206+
- If your app relies on incremental delivery, use a transport library like [`graphql-sse`](https://github.com/enisdenjo/graphql-sse),
207+
but note that it replaces `graphql-http` and must be used as your server handler.
208+
209+
## What's next
210+
211+
`graphql-http` is the reference implementation of the GraphQL-over-HTTP specification,
212+
but there are many other servers you can use to serve your GraphQL API, each with
213+
different features and trade-offs. For a list of other spec-compliant server
214+
implementations see the
215+
[`graphql-http` server list](https://github.com/graphql/graphql-http?tab=readme-ov-file#servers), and don't forget to check out the
216+
[Tools and Libraries page on graphql.org](https://graphql.org/community/tools-and-libraries/?tags=server_javascript).

0 commit comments

Comments
 (0)