How to Set Up a GraphQL API Server on a VPS

GraphQL lets clients request exactly the data they need in a single request, avoiding the over-fetching and multiple round-trips common with REST. This guide covers deploying a GraphQL server on your VPS.

Prerequisites

  • Node.js installed — see How to Install Node.js on Ubuntu & Debian (with NVM)
  • Nginx installed as a reverse proxy

Step 1 — Set Up a Basic GraphQL Server (Apollo Server Example)

mkdir graphql-api && cd graphql-api
npm init -y
npm install @apollo/server graphql express cors body-parser

Step 2 — Define a Schema

const typeDefs = `#graphql
  type User {
    id: ID!
    name: String!
    email: String!
  }

  type Query {
    users: [User!]!
    user(id: ID!): User
  }

  type Mutation {
    createUser(name: String!, email: String!): User!
  }
`;

Step 3 — Define Resolvers

const resolvers = {
  Query: {
    users: async () => await db.query('SELECT * FROM users'),
    user: async (_, { id }) => await db.query('SELECT * FROM users WHERE id = ?', [id]),
  },
  Mutation: {
    createUser: async (_, { name, email }) => {
      const result = await db.query('INSERT INTO users (name, email) VALUES (?, ?)', [name, email]);
      return { id: result.insertId, name, email };
    },
  },
};

Step 4 — Start the Server

const { ApolloServer } = require('@apollo/server');
const { expressMiddleware } = require('@apollo/server/express4');
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');

const app = express();
const server = new ApolloServer({ typeDefs, resolvers });

await server.start();
app.use('/graphql', cors(), bodyParser.json(), expressMiddleware(server));

app.listen(4000, '127.0.0.1', () => console.log('GraphQL server running'));

Step 5 — Manage with PM2

pm2 start index.js --name graphql-api
pm2 startup
pm2 save

Step 6 — Configure Nginx as a Reverse Proxy

server {
    listen 80;
    server_name graphql.yourdomain.com;

    location /graphql {
        proxy_pass http://127.0.0.1:4000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Step 7 — Add HTTPS

sudo certbot --nginx -d graphql.yourdomain.com

Disabling Introspection and Playground in Production

By default, GraphQL servers often expose a schema introspection feature and an interactive query playground — useful in development, but a potential information disclosure risk in production:

const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: process.env.NODE_ENV !== 'production',
});

Implementing Query Complexity Limits (Important for GraphQL Security)

Unlike REST, a single GraphQL query can request deeply nested data, potentially causing excessive database load from what looks like one simple request. Use a query complexity analysis library to reject overly expensive queries before execution.

Rate Limiting a GraphQL Endpoint

Since GraphQL typically uses a single endpoint, per-request rate limiting (see How to Rate Limit an API with Nginx) applies at the endpoint level; consider combining with query complexity limits for more granular protection specific to GraphQL's flexible query nature.

Authentication in GraphQL

app.use('/graphql', expressMiddleware(server, {
  context: async ({ req }) => {
    const token = req.headers.authorization?.split(' ')[1];
    const user = token ? verifyToken(token) : null;
    return { user };
  },
}));

See How to Set Up API Authentication with JWT for the underlying token verification approach.

Common Errors

"Cannot query field X on type Y" — the client's query doesn't match your defined schema; verify field names and types match exactly.

Slow queries — often caused by the N+1 query problem in resolvers fetching related data individually per item; use a batching/caching library (like DataLoader) to resolve this.

Best Practices

  • Disable introspection and playground in production
  • Implement query complexity limits to prevent resource-exhaustion attacks
  • Watch for N+1 query patterns in resolvers, same as any ORM-based application

Continue Reading

Browse more articles in Object Storage, Messaging & APIs.

  • graphql, apollo server, graphql api, graphql deployment
  • 0 Utenti hanno trovato utile questa risposta
Hai trovato utile questa risposta?

Articoli Correlati

How to Set Up Self-Hosted S3-Compatible Object Storage with MinIO

MinIO is a high-performance, self-hosted object storage server compatible with the S3 API —...

How to Use Object Storage for Application File Uploads

Storing user-uploaded files directly on your application server's disk creates scaling and...

How to Install and Configure RabbitMQ on a VPS

RabbitMQ is a widely-used, robust message broker — enabling applications to communicate...

How to Install and Configure Redis as a Message Queue

Redis, primarily known as a cache, also works well as a lightweight message queue for simpler use...

How to Build and Secure a REST API on a VPS

This guide covers the essential security and architecture practices for deploying a REST API on...