DEV Community

Cover image for migrate your redwood graphQL API with graphQL-helix and envelop

migrate your redwood graphQL API with graphQL-helix and envelop

full stack web dev
Originally published at Updated on ・6 min read

Note: For the official migration guide please see Using GraphQL Envelop+Helix in Redwood v0.35+. We ask that you direct any comments there. We would love your feedback! 😄

Back in January the Redwood team decided to modify the internals of Redwood to allow users to specify their own client instead of using Apollo Client. Within weeks @marceloalves created a new package for a React Query Provider and @tobbe showed how you could Switch to another GraphQL Client with graphql-hooks.

But what if you wanted to use your GraphQL server of choice?

Over the last two months Dotan Simha from The Guild along with assistance from certified Redwood Whisperer @dthyresson have been working on similar modifications which will allow users to migrate away from Apollo Server to a different GraphQL server.

Hi, people of the Redwood! :)

I created an initial PR for migrating from apollo-server-lambda to Envelop and GraphQL-Helix. The goal of this PR is to normalize the incoming HTTP requests and try to handle them in a generic way. Also, since the request is detached from the handler, we can use any GraphQL library for execution.

While graphql-helix provides the basic pipeline and the initial request normalization, envelop provides the connection to the GraphQL execution, and allow to enrich the entire GraphQL execution pipeline with custom code (custom context building, parser cache, validation cache, tracing, metrics collection and more).

Dotan Simha - Partial normalization of Lambda request (April 25, 2021)

The initial PR, Partial normalization of Lambda request for migration to Envelop, laid the foundation for using GraphQL-Helix and Envelop.

  • GraphQL Helix is a framework and runtime agnostic collection of utility functions for building your own GraphQL HTTP server.
  • Envelop is a lightweight library allowing developers to easily develop, share, collaborate and extend their GraphQL execution layer. Envelop is the missing GraphQL plugin system.

Earlier this week I released GraphQL Helix, a new JavaScript library that lets you take charge of your GraphQL server implementation.

There's a couple of factors that pushed me to roll my own GraphQL server library:

  • I wanted to use bleeding-edge GraphQL features like @defer, @stream and @live directives.
  • I wanted to make sure I wasn't tied down to a specific framework or runtime environment.
  • I wanted control over how server features like persisted queries were implemented.
  • I wanted to use something other than WebSocket (i.e. SSE) for subscriptions.

Unfortunately, popular solutions like Apollo Server, express-graphql and Mercurius fell short in one or more of these regards, so here we are.

Daniel Rearden - Building a GraphQL server with GraphQL Helix (November 5, 2020)

Create Redwood App

The code for this project can be found on my GitHub.

yarn create redwood-app redwood-envelop
cd redwood-envelop
Enter fullscreen mode Exit fullscreen mode

Open schema.prisma in api/db and add the following schema.

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")

generator client {
  provider      = "prisma-client-js"
  binaryTargets = "native"

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  body      String
  createdAt DateTime @default(now())
Enter fullscreen mode Exit fullscreen mode

Provision a PostgreSQL database with Railway

First you need to create a Railway account and install the Railway CLI.

railway login
railway init
railway add
Enter fullscreen mode Exit fullscreen mode

Add a PostgreSQL plugin to your Railway project and then set the DATABASE_URL inside your .env file.

echo DATABASE_URL=`railway variables get DATABASE_URL` > .env
Enter fullscreen mode Exit fullscreen mode

Setup database with prisma migrate dev and generate scaffold

Running yarn rw prisma migrate dev generates the folders and files necessary to create a new migration. We will name our migration posts-table.

yarn rw prisma migrate dev --name posts-table
yarn rw g scaffold post
yarn rw dev
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:8910/posts to create a couple blog posts.


Configure project to use Envelop

Add useEnvelop=true to the [experimental] section in your redwood.toml config. This lets the dev-server know how to handle the response.

  port = 8910
  apiProxyPath = "/.redwood/functions"
  port = 8911
  open = true
  esbuild = false
  useEnvelop = true
Enter fullscreen mode Exit fullscreen mode

Add @redwoodjs/graphql-server to api dependencies

yarn workspace api add @redwoodjs/graphql-server
Enter fullscreen mode Exit fullscreen mode

Define logger in /api/src/lib/logger.js and update import to graphql-server package

// api/src/lib/logger.js

import { createLogger } from '@redwoodjs/graphql-server/logger'

export const logger = createLogger({
  options: { level: 'info', prettyPrint: true },
Enter fullscreen mode Exit fullscreen mode

Add graphql-server package to graphql.js function and loggerConfig to createGraphQLHandler

// api/src/functions/graphql.js

import {
} from '@redwoodjs/graphql-server'

import schemas from 'src/graphql/**/*.{js,ts}'
import { db } from 'src/lib/db'
import { logger } from 'src/lib/logger'
import services from 'src/services/**/*.{js,ts}'

export const handler = createGraphQLHandler({
  loggerConfig: {
    options: {
      operationName: true,
      tracing: true
  schema: makeMergedSchema({
    services: makeServices({ services }),
  onException: () => {
Enter fullscreen mode Exit fullscreen mode

Apollo plugins are not currently supported and must be removed. However, there may be equivalent Envelop plugins. These can be added in the createGraphQLHandler configuration options in extraPlugins. extraPlugins accepts an array of plugins.

Currently used plugins

Enter fullscreen mode Exit fullscreen mode

Change the imports to use the new graphql-server package if your services raise any errors based on ApolloError such as UserInputError or ValidationError.

import { UserInputError } from '@redwoodjs/graphql-server'
Enter fullscreen mode Exit fullscreen mode

If you have any other @redwoodjs/api imports in your project make sure to change them to @redwoodjs/graphql-server.

Restart development server and send a query

yarn rw dev
Enter fullscreen mode Exit fullscreen mode


Add HomePage and PostsCell

yarn rw g page home /
yarn rw g cell posts
Enter fullscreen mode Exit fullscreen mode
// web/src/components/PostsCell/PostsCell.js

export const QUERY = gql`
  query PostsQuery {
    posts {

export const Loading = () => <div>Almost there...</div>
export const Empty = () => <div>WHERE'S THE POSTS?</div>
export const Failure = ({ error }) => <div>{error.message}</div>

export const Success = ({ posts }) => {
  return => (
    <article key={}>
Enter fullscreen mode Exit fullscreen mode
// web/src/pages/HomePage/HomePage.js

import PostsCell from 'src/components/PostsCell'

const HomePage = () => {
  return (
      <PostsCell />

export default HomePage
Enter fullscreen mode Exit fullscreen mode

Setup Netlify Deploy

Generate the configuration file needed for deploying to Netlify with the following setup command.

yarn rw setup deploy netlify
Enter fullscreen mode Exit fullscreen mode

Push Project to GitHub

Create a blank repository at and push the project to your GitHub.

git init
git add .
git commit -m "the guilded age of redwood"
git remote add origin
git push -u origin main
Enter fullscreen mode Exit fullscreen mode

Connect Repo to Netlify

Go to Netlify and connect the repo. Include the DATABASE_URL environment variable and add ?connection_limit=1 to the end of the connection string. You can also give your site a custom domain such as redwood-envelop.



Test the API with a query

query getPosts {
  posts {
Enter fullscreen mode Exit fullscreen mode


Is Redwood still Redwood without Apollo?

RedwoodJS was originally architected around Apollo Client on the web side and Apollo Server on the api side. These two libraries were fundamental to the development of not only Redwood but the entire GraphQL ecosystem. Apollo itself was born from the ashes of the Meteor Development Group.

Meteor pursued a similar philosophy of fullstack JavaScript now employed by Redwood. By bringing the decoupled Apollo pieces of client and server together into a single fullstack application it felt like the original dream of Meteor was finally coming to fruition. But GraphQL is itself about decoupling the frontend from the backend so that one side is never too heavily tied to the other.

This has allowed Redwood to pursue other GraphQL clients and servers that continue to evolve and improve and engage with the open source developer community. The free market of repositories is alive and well, and we will see many more experiments in the coming future.

Discussion (0)