Skip to main content


Let's deploy our application to Railway. There are a few ways to deploy an application to Railway. We use its support to deploy GitHub repositories, which allows us to deploy our application automatically whenever we publish it to GitHub.

We will explore two ways to use Postgres:

  • Railway-provided Postgres: In this arrangement, we co-locate the app and database in Railway's infrastructure.

  • External Postgres: In this arrangement, we use a provider specializing in Postgres and connect to it from Railway. We will illustrate using Neon, a "multi-cloud fully managed Postgres with a generous free tier". This free tier is perfect for this tutorial. If you want to use other Postgres providers, the basic steps are the same: create a database and set the EXO_POSTGRES_URL environment variable to point to it.

Creating a new application

Let's start from scratch to keep this tutorial standalone. However, you can also use an existing application like the concert management application developed in the Application Tutorial guide.

Let's create a new application:

exo new todo
cd todo

Creating Deployment Files

The exo deploy railway command simplifies deploying Exograph application to Railway by creating Dockerfile.railway and railway.yaml files. The Dockerfile.railway file has two parts: the first part builds the exo_ir file and performs database migration, and the second part launches the Exograph server with that exo_ir file. The railway.yaml points to Dockerfile.railway. You may customize these files to suit your needs (for example, adding environment variables specific to your app). You should commit these files to your repository.

The difference between using Railway and external databases is the value we pass to the --use-railway-db option. If you don't specify it, Exograph will ask you the choice of database.

exo deploy railway --use-railway-db=true

This command creates the files described earlier and prints instructions to deploy the application to Railway.


If you intend to consume the API through a web application, update Dockerfile.railway to set EXO_CORS_DOMAINS=<comma-separated-domains>.

Pushing to GitHub

Push the application to GitHub, which allows automatic deployment upon pushing to the specified GitHub branch.

git commit -am "Initial commit"

Now, create a new repository on GitHub and push the code to it.

Deploying to Railway

Deploying the application to Railway is simple! Here is a video showing the process:

As shown in the video, we need to:

  • Create a new Railway project.
  • Add a "New Service" to the project and select "GitHub Repo" pointing to the repository we created earlier
  • Provision a new database on that project
  • Add "Variable Reference" to the service for DATABASE_URL and DATABASE_PRIVATE_URL environment variables

In either case,

  • Wait for the deployment to complete
  • Click on "Add a Domain" and note the server URL

Testing the app

Since we didn't set the EXO_INTROSPECTION environment variable, it will be false by default, which is a good practice in production. This default makes the GraphQL playground unavailable with the production URL. Thanks to exo playground command, this is not a problem. Run the following command to open the playground:

exo playground --endpoint https://<server-url>/graphql

This will print a URL to the playground. Open it in your browser. You should see the playground.

Starting playground server connected to the endpoint at: https://<server-url>/graphql
- Playground hosted at:

Now open http://localhost:9876/playground to see the GraphiQL Playground. You can execute queries and mutations. See the Getting Started guide for more details.

Updating the application

Updating the application is a simple matter of pushing the repository to GitHub. Railway will automatically deploy the new version. The first stage of Dockerfile.railway will attempt migration as well. The migration will succeed if you change the Exograph model without destructive changes. Otherwise, it will fail, and the deployment will fail (the older deployment will continue to serve the traffic). If that happens, you should apply migrations manually. See Migrations for more information.