Fastify GraphQL API Stack: with Mercurius & Nexus
Tags: webdev, node, typescript, graphql
Published: 2022-08-24 12:39:58

---
title: "Fastify GraphQL API Stack: with Mercurius & Nexus"
published: "true"
description: "Fastify GraphQL API Stack: node API stack using TypeScript, Mercurius for GraphQL, Nexus, Prisma with PostgreSQL and uvu for fast testing."
tags: "webdev, node, typescript, graphql"
canonical_url: "https://rodneylab.com/fastify-graphql-api-stack/"
cover_image: "https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h0v8nn5eui1adevoi6cm.png"
---

## 📈 Why Work on a New GraphQL API Stack?

Here I talk a little about a Fastify GraphQL API stack I have assembled and some of the 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 only remaining original components and needed a bit of refactoring.  For those reasons it seemed a good time to put together a fresh demo repo.

{% embed https://www.youtube.com/embed/I6ypD7qv3Z8 %}

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&rsquo;ll talk a little about what the elements bring to the party, but if you just want to see the code, its 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, <a aria-label="browse fastify plugins" href="https://www.fastify.io/ecosystem/">fastify has an extensive ecosystem of over 200 plugins</a> 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&rsquo;t touched in a while and bring it up-to-date.

Fastify DX is in the pipeline.  It brings <a aria-label="Open the Fastify D X Git Hub repo" href="https://github.com/fastify/fastify-dx/tree/main/packages/fastify-dx-svelte">Vite-powered front end solutions in Svelte</a>, 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.

## 🌡 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.

![Fastify GraphQL API Stack: screen capture shows GraphiQL with query in left pane, response in the middle and schema docs on the right](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03t772n8bywsyb6eunss.png)

<a aria-label="Read Mercurius integration testing docs" href="https://mercurius.dev/#/docs/integrations/mercurius-integration-testing">Mercurius also has its own testing integration</a> 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 initialise 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&rsquo;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.

```typescript
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 you 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.

```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 <a href="https://nexusjs.org/docs/getting-started/tutorial#overview">Nexus tutorial was super helpful</a>.  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 the your database entities and their relations.  The Prisma VSCode 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.  <a aria-label="See Kent C Dodds Tweet on Prisma" href="https://twitter.com/kentcdodds/status/1400893865196879873">Kent C Dodds is a Prisma fan too!</a>  Give it a spin on your next pet project if you haven&rsquo;t yet tried it out.

### uvu Testing

uvu is a fast test runner.  There&rsquo;s <a aria-label="Open post on using uvu with Fastify" href="https://rodneylab.com/using-uvu-typescript-api-testing/">another article on setting up uvu with Fastify</a> so we won&rsquo;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 <a aria-label="Read about running fast Svelte componetn unit tests with uvu" href="https://rodneylab.com/sveltekit-uvu-testing/">test UI components, in Svelte</a> 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 to them to fetch requests and injecting them into that live Fastify instance.  

```typescript
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:

```yaml
services:
  postgres:
    image: postgres:14.4
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: fastify
    volumes:
      - postgres:/var/lib/postgresql/data
    ports:
      - '5432:5432'

  postgres-test:
    image: postgres:14.4
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: fastify
    ports:
      - '5435:5432'

volumes:
  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`:

```plaintext
# Environment variables declared in this file are automatically made available to Prisma.

# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema

# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.

# See the documentation for all the connection string options: https://pris.ly/d/connection-strings

DATABASE_URL="postgresql://postgres:postgres@localhost:5435/fastify?schema=public"
```

## 🙌🏽 Fastify GraphQL API Stack: Wrapping Up

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

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

Please take a look at the stack code if you haven&rsquo;t yet.  It&rsquo;s in the <a aria-label="Open the fastify mercurius nexus Graph Q L A P I Git Hub repo" href="https://github.com/rodneylab/fastify-mercurius-nexus-graphql-api">RodneyLab GitHub repo</a>.  I hope you find it useful for your own projects. Keen to hear your feedback on how it can be further modernised.  Especially if you know new related tools which I have not included.

## 🙏🏽 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 <a aria-label="Support Rodney Lab via Buy me a Coffee" href="https://rodneylab.com/giving/">consider supporting me through Buy me a Coffee</a>.

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 <a aria-label="Reach out on Twitter" href="https://twitter.com/messages/compose?recipient_id=1323579817258831875">@askRodney</a> on Twitter and also <a aria-label="Contact Rodney Lab via Telegram" href="https://t.me/askRodney">askRodney on Telegram</a>. Also, see <a aria-label="Get in touch with Rodney Lab" href="https://rodneylab.com/contact">further ways to get in touch with Rodney Lab</a>. I post regularly on <a aria-label="See posts on Astro" href="https://rodneylab.com/tags/astro/">Astro</a> as well as <a aria-label="See posts on svelte kit" href="https://rodneylab.com/tags/sveltekit/">SvelteKit</a>. Also <a aria-label="Subscribe to the Rodney Lab newsletter" href="https://rodneylab.com/about/#newsletter">subscribe to the newsletter to keep up-to-date</a> with our latest projects.