2. Deploying Apollo Server

πŸš€ Deploying our server

Let's get our up and running in production using Railway!

To get started, click the button below ⬇️

Deploy on Railway

Then, walk through the deploy setup steps in Railway.

  1. Click Deploy now.


    Railway template with Deploy now button

  2. Fill in your repository details: where to clone the repo and what to name it.


    Repository details

  3. Railway automatically triggers a new deployment of our app. And after a few minutes, we should see it worked!


    Deployment success

  4. Next, we want to our server at a public URL on the internet. To do this, we'll need to generate a domain. Go to your app's Settings tab, and click the Generate Domain button under the Domains header.


    Deployment success

This will automatically create a production URL that we'll use in our client app later on.

Let's click on the generated URL and… uh-oh!

Production URL with PORT error

We need to make one change to our code. Railway needs our server to run on a port specified by the PORT environment variable, which is set behind the scenes.

πŸ”Œ Setting the PORT

Let's open up our server repo. To find this repo, head over to Settings, scroll down to Service and find the Source repo link.


Source repo

Click the link to find your copy of the GitHub repo, where you're free to make any changes you'd like!

Note: The following instructions assume you are comfortable with cloning the repo, making changes in your local code editor and using Git to commit and push those changes back up to the repo. However, you can also use the GitHub web UI to make the same changes! Refer to the collapsible section below for instructions on using the GitHub web UI.

For now, we want to make one specific change: setting the PORT for to listen to.

In the src folder, open up the index.js file.

Right now, by default, is listening on port 4000. We need to customize this by updating our server's options to include a listen object with a port key.

const { url } = await startStandaloneServer(server, {
context: async () => {
return {
dataSources: {
trackAPI: new TrackAPI(),
listen: {
port: process.env.PORT || 4000,

The port property should be set to process.env.PORT (with PORT in all-caps). To make sure our server still works locally on our own machines however, we'll add an "or" (||) and specify 4000 as our port number.

And that's it! Let's make sure to add and commit these changes, and make sure it lands on the GitHub repo's main branch.

Code Challenge!

Edit the code below to configure Apollo Server to listen to a port specified by process.env.PORT, or if that doesn't exist, a hard-coded port number 4000.

Back in Railway, we should see the new commit trigger another deploy.

Let's try this again. Go back to that generated URL (give it a few minutes to update!) and... we see the landing page for in production! Yay! πŸŽ‰

Apollo Server landing page in production

But this page looks a bit different from what we would normally see if we had run our server locally.

We don't have the option to our server through . This is because Railway automatically set the NODE_ENV environment variable to production, which alerts our to switch itself to production as well, automatically disabling .

πŸ€” What is GraphQL introspection?

is a feature that enables us to a for information about the underlying schema. This includes data like types, , and field-level descriptions. Tools like use introspection to build and run queries.

Illustration of introspection in development environments

The problem is that having in production can be a major security issue. It exposes all of our 's structure and what we can do with it to the whole world. In most cases, that's not what we want! This is why disables by default in a production environment.

Illustration of introspection in production environments, where introspection is turned off
What information can we query from a GraphQL server through the introspection feature?
Which of these statements are true about the introspection feature?

Even still, our server is live in production! πŸŽ‰ Now we just need to use it. To pull our pieces together, let's tackle the client app next.