api/index.js handler that exports your Apollo server, you ensure the schema is loaded dynamically at runtime without a persistent process. This guide walks through the necessary file structure and configuration files to achieve a successful deployment.
Prerequisites and Environment Setup
Before deploying, ensure your local development environment matches the requirements for serverless execution. You need Node.js installed locally, preferably version 18 or higher, to support modern async/await patterns used in Apollo resolvers. Initialize your project with npm init -y and install the core dependencies: @apollo/server, graphql, and vercel. It is critical to avoid bundling heavy libraries like MongoDB drivers directly into the function payload if possible; instead, rely on network connections from the serverless instance.
Create a basic directory structure. Your root should contain package.json, a schema.graphql file for your type definitions, and an src folder for your resolver logic. Vercel expects specific routing rules, so clarity in your file organization prevents common deployment errors related to asset paths.
Configuring the Apollo Server Handler
The core of your deployment is the API handler. Create a file named api/index.js at the root of your project. This file acts as the single entry point for all GraphQL requests. Inside this file, import the necessary modules from @apollo/server and create your executable schema using makeExecutableSchema.
const { ApolloServer } = require('@apollo/server');
const { startServerAndCreateServerlessHandler } = require('@as-integrations/vercel');
const fs = require('fs');
const path = require('path');
const { makeExecutableSchema } = require('@graphql-tools/schema');
// Load schema from file
const typeDefs = fs.readFileSync(path.join(__dirname, '../schema.graphql'), 'utf8');
// Define resolvers
const resolvers = {
Query: {
hello: () => 'Hello World',
},
};
const schema = makeExecutableSchema({ typeDefs, resolvers });
async function start() {
const server = new ApolloServer({ schema });
return startServerAndCreateServerlessHandler(server);
}
module.exports = start();
Note the use of @as-integrations/vercel. This package provides the startServerAndCreateServerlessHandler function, which correctly adapts the Apollo server lifecycle to Vercel’s request/response model. Without this integration, you may encounter issues where the server fails to initialize properly within the cold-start constraints of serverless environments.
Vercel Configuration File
To ensure Vercel recognizes your API route, you must provide a vercel.json configuration file in the root directory. This file maps the api/index.js file to the correct build output. While Vercel often auto-detects Next.js projects, explicit configuration is safer for pure Node.js GraphQL apps.
{
"builds": [
{
"src": "api/index.js",
"use": "@vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "/api/index.js"
}
]
}
The builds array tells Vercel to treat api/index.js as a Node.js function. The routes section ensures that any request to your domain is forwarded to this handler. If you are hosting static assets alongside your API, you may need to adjust the routes to exclude static file paths from hitting the GraphQL endpoint.
Handling Dependencies and Build Steps
During the deployment process, Vercel runs npm install automatically. Ensure that all production dependencies are listed in dependencies and not just devDependencies. A common pitfall is forgetting to include @apollo/server in the main dependencies list, which results in a Cannot find module error during runtime.
If your application uses external databases, configure them via environment variables in the Vercel dashboard. Do not hardcode connection strings. For example, set a variable named MONGO_URI in your project settings and access it via process.env.MONGO_URI in your resolver code. This keeps your credentials secure and allows different configurations for preview deployments versus production.
Deployment and Verification
Connect your Git repository to Vercel. During the setup, verify that the framework preset is detected as "Other" or "Custom," since Vercel might try to apply Next.js defaults incorrectly. Once deployed, test your endpoint by appending /graphql to your URL and sending a POST request with a valid GraphQL query in the body.
If you encounter issues with large bundle sizes, consider splitting your resolvers into smaller modules and importing only what is needed. This reduces the cold-start time for your serverless function. For more complex troubleshooting regarding asset folders or deployment failures, refer to our guide on Deployment to Vercel Failed: Troubleshooting JS, CSS, and Asset Folders.
Frequently Asked Questions
Why does my Apollo server return a 500 error on Vercel?
This usually indicates an unhandled exception during the initialization phase or a missing dependency. Check the Vercel logs for stack traces, focusing on module resolution errors or database connection timeouts.
Can I use WebSocket subscriptions with Apollo on Vercel?
Standard Vercel serverless functions do not support persistent WebSocket connections required for subscriptions. You would need to use a managed service like AWS AppSync or deploy to a platform that supports WebSockets, such as Railway or Render.
How do I handle CORS policies for my GraphQL endpoint?
Apollo Server handles CORS automatically if configured correctly. Ensure your cors option in the Apollo Server constructor includes the origins of your frontend application. Vercel also applies its own security headers, so verify they do not conflict with your client-side requests.
What is the best way to manage environment variables?
Use the Vercel Dashboard to add environment variables under the Project Settings > Environment Variables section. These variables are automatically injected into your serverless functions at runtime, ensuring they are available in process.env.
Does Vercel cache GraphQL responses?
Vercel does not cache dynamic POST requests to your GraphQL endpoint by default. However, if you implement caching headers in your resolvers, Vercel’s edge network may cache GET requests if you choose to expose a REST-like interface for specific queries.