Opens an external site in a new window
Mental Health Awareness Month
“Community”
RODNEY LAB
  • Home
  • Plus +
  • Newsletter
  • Links
  • Profile
RODNEY LAB
  • Home
  • Plus +
  • Newsletter
  • Links

Fastify GraphQL API Stack: with Mercurius & Nexus # Fastify GraphQL API Stack: with Mercurius & Nexus #

blurry low resolution placeholder image Fastify GraphQL API Stack
  1. Home Rodney Lab Home
  2. Blog Posts Rodney Lab Blog Posts
  3. Backend Backend Blog Posts
<PREVIOUS POST
NEXT POST >
LATEST POST >>

Fastify GraphQL API Stack: with Mercurius & Nexus #

Updated 4 months ago
7 minute read
Gunning Fog Index: 6.6
2 comments
Content by Rodney
blurry low resolution placeholder image Author Image: Rodney from Rodney Lab
SHARE:

📈 Why Work on a New GraphQL API Stack? #

Here I talk a little about a Fastify GraphQL API stack I have assembled and some choices made. This stack is something I will use as a staring point for new node backends which I want to interface with using GraphQL queries. I had previously used something based on a 14-hour Ben Awad YouTube tutorial. That tutorial turns two years old this week and has amassed an impressive 1.1 million views over that time. However, two years is a long time in tech, and over that time I have swapped out parts as newer tools got introduced. The latest change saw me swap out TypeGraphQL for Nexus. TypeGraphQL was just about one of the few remaining original components and needed a bit of refactoring. For those reasons, it seemed a good time to put together a fresh demo repo.

Ben Awad: Fullstack React GraphQL TypeScript Tutorial

The original stack was Node Express, TypeScript, Apollo, PostgreSQL, TypeORM and TypeGraphQL. My latest incarnation still has TypeScript and PostgreSQL but uses Fastify as a node server, Mercurius (from the Fastify team) as the GraphQL server, Prisma (replacing TypeORM) and Nexus instead of TypeGraphQL. I also use uvu for unit testing. I’ll talk a little about what the elements bring to the party, but if you just want to see the code, it’s on the Rodney Lab GitHub repo (link further down the page).

🧑🏽‍🦼 Fastify #

Fastify forms the foundations of the stack. It is built to be a highly performant node server and an alternative to Express. As well as being fast, fastify has an extensive ecosystem of over 200 plugins  from the community and core team. Ones you are likely to use most often are @fastify/cookie, @fastify/redis and @fastify/session. These are generally pretty quick to integrate and have minimal configuration. One consideration to take account of though is that Fastify and the plugins are always being improved. That means it can take a while to dust off a project you haven’t touched in a while and bring it up-to-date.

Fastify DX is in the pipeline. It brings Vite-powered front end solutions in Svelte , React and other frameworks to Fastify, and is already in alpha. This will let you create full stack apps using Fastify together with your preferred frontend.

🗳 Poll #

Will you give Fastify DX a try?
Voting reveals latest results.

🌡 Mercurius #

I was using Apollo GraphQL server previously but opted for Mercurius for tighter Fastify integration. It was a GraphiQL web frontend like Apollo, which is handy for debugging your queries.

blurry low resolution placeholder image Fastify GraphQL API Stack: screen capture shows GraphiQL with query in left pane, response in the middle and schema docs on the right
Fastify GraphQL API Stack: GraphiQL Screenshot

Mercurius also has its own testing integration  for integration testing.

⛓ Nexus #

Nexus is kind of glue for your database and GraphQL. It plays a similar role as TypeGraphQL; helping you generate GraphQL schemas from your TypeScript models for your apps entities. You use the generates schema to initialize your GraphQL server. The way for coding up your entities is quite different, comparing TypeGraphQL to Nexus; switching involved a bit of refactoring. With TypeGraphQL, you define resolvers (functions detailing what data to respond to each GraphQL query or mutation with) as classes and decorate them with your predefined GraphQL types.

Here’s the Nexus resolver for a basic Hello query. It just responds with the text Hello everybody!. Typically, though, you will take in input from the query, process it, perhaps checking for a logged-in user and then querying your database to form the response data.

    
import { extendType } from 'nexus';
export const HelloQuery = extendType({
type: 'Query',
definition(t) {
t.field('hello', {
type: 'String',
resolve() {
return 'Hello everybody!';
},
});
},
});

I like how Nexus outputs a GraphQL schema file (schema.graphl) into your project folder and also a TypeScript file with all the types generated from your schema (nexus-typegen.ts in the repo). This all comes from the resolver and entity model definitions which you provide.

schema.graphql
graphql
    
### This file was generated by Nexus Schema
### Do not make changes to this file directly
type Mutation {
createDraft(body: String!, title: String!): Post!
deleteDraft(draftId: Int!): Boolean!
publish(draftId: Int!): Post!
}
type Post {
body: String
id: Int
published: Boolean
title: String
}
type Query {
drafts: [Post]!
hello: String
posts: [Post]
}

It took a bit of getting used to and the Nexus tutorial was super helpful . That uses Apollo Server, Jest, and SQLite with Prisma to build out a basic GraphQL API for creating and editing blog posts. I followed along but added a few extra queries to cement my understanding and used Mercurius, uvu and PostgreSQL instead of Apollo, Jest and SQLite. The code in the repo is based on the tutorial but with this new stack and a few extra queries.

What does Prisma Bring to the Party? #

Prisma is fantastic for working with databases in your projects. You create a schema for your database (can be PostgreSQL, SQLite or others) and it generates TypeScript types for you and a set of utility functions for CRUD operations. The schema is a single file listing your database entities and their relations. The Prisma VS Code extension helps create and format it. Prisma also helps generate migration files whenever you update your database schema. I use it with Remix sites as well as API projects. Kent C Dodds is a Prisma fan too!  Give it a spin on your next pet project if you haven’t yet tried it out.

uvu Testing #

uvu is a fast test runner. There’s another article on setting up uvu with Fastify so we won’t go into it in detail here. It has a much lighter footprint than Jest and sits in the same class as Vitest. You can also use uvu to unit test UI components, in Svelte for example. In the repo, we have a little helper function within a test context which spins up a new Fastify instance for testing. It then takes GraphQL queries as an input, converting them to fetch requests and injecting them into that live Fastify instance.

    
export function createTestContext(): TestContext {
const ctx = {} as TestContext;
let serverInstance: FastifyInstance | null = null;
const prismaCtx = prismaTestContext();
test.before(async () => {
serverInstance = await build({ logger: false });
});
test.before.each(async (meta) => {
console.log(meta.__test__);
const db = await prismaCtx.before();
async function request(query: string, variables = {} as Record<string, string>) {
return serverInstance?.inject({
method: 'POST',
url: 'graphql',
headers: { 'content-type': 'application/json' },
payload: { query, variables },
});
}
Object.assign(ctx, { db, request });
});

The repo code includes a docker-compose.yml file with two PostgreSQL instances, one for dev and another for testing:

docker-compose.yml
yaml
    
1 services:
2 postgres:
3 image: postgres:17.2@sha256:d37d2c160d34430877c802e5adc22824a2ad453499db9bab1a2ceb2be6c1a46f
4 restart: always
5 environment:
6 POSTGRES_USER: postgres
7 POSTGRES_PASSWORD: postgres
8 POSTGRES_DB: fastify
9 volumes:
10 - postgres:/var/lib/postgresql/data
11 ports:
12 - '5432:5432'
13
14 postgres-test:
15 image: postgres:17.2@sha256:d37d2c160d34430877c802e5adc22824a2ad453499db9bab1a2ceb2be6c1a46f
16 environment:
17 POSTGRES_USER: postgres
18 POSTGRES_PASSWORD: postgres
19 POSTGRES_DB: fastify
20 ports:
21 - '5435:5432'
22
23 volumes:
24 postgres:

Notice, we omit the volumes field on the test instance because we do not need data to persist in the test environment. As well as this, the second instance listens on a different port (5435), but connects to 5432 on your machine. For this to work, we have two .env files and set DATABASE_URL in the test one to use port 5435:

.env.test.EXAMPLE
plaintext
    
1 # Environment variables declared in this file are automatically made available to Prisma.
2
3 # See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
4
5 # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
6
7 # See the documentation for all the connection string options: https://pris.ly/d/connection-strings
8
9 DATABASE_URL="postgresql://postgres:postgres@localhost:5435/fastify?schema=public"

🙌🏽 Fastify GraphQL API Stack: Wrapping Up #

We had a look at an up-to-date Fastify GraphQL API stack and some reasoning for the choices made. In particular, we saw:

  • some plugins in the Fastify ecosystem,
  • what Nexus is and some differences to TypeGraphQL,
  • some code snippets from the stack, like injecting GraphQL queries into a running Fastify server for unit testing.

Please have a look at the stack code if you haven’t yet. It’s in the Rodney Lab GitHub repo . I hope you find it useful for your own projects. Keen to hear your feedback on how it can be further modernized. Especially if you know new related tools, which I have not included.

🏁 Fastify GraphQL API Stack: Summary #

Is there a GraphQL server for Fastify? #

There is a plugin for Apollo Server to make it work with Fastify. Mercurius is an alternative GraphQL server, from the Fastify team. It is performant, just like Fastify, and offers tight with Fastify, as you would expect. On top, it works well with Nexus, TypeGraphQL and Prisma, and has fine docs with integration examples. Mercurius has a GraphiQL server built in, like Apollo. This is fantastic for debugging queries.

What alternative are there to TypeGraphQL? #

TypeGraphQL is a tool for stitching together GraphQL APIs. It helps you generate GraphQL schema from TypeScript classes describing your data model. Nexus is an alternative offering similar functionality. Both are code-first solutions — you write code, which the tool uses to create a GraphQL schema for you. That is, rather than starting out by writing the GraphQL schema. While you use decorators on TypeScript classes to spec out your data model with TypeGraphQL, Nexus uses regular TypeScript functions. For a new project, either is probably just as easy to get going on. Switching from one to the other requires some refactoring, though.

How can you set up a PostgreSQL database locally for testing? #

You can use Docker and the docker-compose tool to create a local test database together with a dev one. In your `docker-compose.yml` file create a second database and set ports on this one for example to `'5435:5432'` so Docker will be listening on post 5435 (in this case) for PostgreSQL queries but map them to port 5432 on your machine. For the second test instance, if you do not need the test data to persist, you can omit the volumes field. You can create separate `.env.dev` and `.env.test` environment variable files, containing the URL for the required database. Then, using with the `dotenv` package, in your test setup file, include the lines `import { config } from 'dotenv';` and `config({ path: '.env.test' });`.

🙏🏽 Fastify GraphQL API Stack: Feedback #

Have you found the post useful? Would you prefer to see posts on another topic instead? Get in touch with ideas for new posts. Also, if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a few dollars, euros or pounds, then please consider supporting me through Buy me a Coffee.

blurry low resolution placeholder image ask Rodney X (formerly Twitter) avatar

Rodney

@askRodney

Just dropped a new post on a GraphQL API template written in TypeScript using 🔥 Fastify as server, Mercurius, Nexus and Prisma with PostgreSQL, also uvu!

Hopefully useful if you want to combine some of these on a project.

#askRodney #api @fastifyjs https://t.co/33siG2UHmY

— Rodney (@askRodney) August 19, 2022

Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on Twitter and also askRodney on Telegram . Also, see further ways to get in touch with Rodney Lab. I post regularly on Astro as well as SvelteKit. Also, subscribe to the newsletter to keep up-to-date with our latest projects.

Thanks for reading this post. I hope you found it valuable. Please get in touch with your feedback and suggestions for posts you would like to see. Read more about me …

blurry low resolution placeholder image Rodney from Rodney Lab
TAGS:
BACKENDGRAPHQLTYPESCRIPTPOSTGRESQL

Related Posts

blurry low resolution placeholder image SvelteKit GraphQL Type Generation

SvelteKit GraphQL Type Generation

sveltekit
graphql
typescript
<PREVIOUS POST
NEXT POST >
LATEST POST >>

Leave a comment …

Your information will be handled in line with our Privacy Policy .

Comments

  • Max

    Thanks. I wish it were a tutorial or video, though...

    3 years ago
    • Rodney

      Hi Max, thanks for feedback... happy to put something together. Let me know if you have some ideas on the kind of API to build in the tutorial
      3 years ago

Ask for more

1 Nov 2022 — Astro Server-Side Rendering: Edge Search Site
3 Oct 2022 — Svelte eCommerce Site: SvelteKit Snipcart Storefront
1 Sept 2022 — Get Started with SvelteKit Headless WordPress

Copyright © 2020 – 2025 Rodney Johnson. All Rights Reserved. Please read important copyright and intellectual property information.

  • Home
  • Profile
  • Plus +
  • Newsletter
  • Contact
  • Links
  • Terms of Use
  • Privacy Policy
We use cookies  to enhance visitors’ experience. Please click the “Options” button to make your choice.  Learn more here.