Riding on Railway
The driving principle behind Exograph is to make it easy for developers to build their backends by letting them focus only on inherent—not incidental—complexity; Exograph should handle everything else. With Exograph, you can create a GraphQL server with a rich domain model with authorization logic, Postgres persistence, and JavaScript/TypeScript business logic in just a few lines of code. But what about deploying to the cloud?
The new platform-as-a-service offerings make deploying Exograph apps easy, and we make it easier by providing specific integrations. In this blog, I will focus on Railway. With its Postgres support and GitHub integration, you can create an Exograph server from scratch and deploy it in under three minutes!
A quick overview of Exograph
Let's take a quick look at Exograph from a deployment perspective, which will make the Railway integration easy to understand. Exograph separates the build and execution steps and ships two corresponding binaries: exo
and exo-server
.
The exo
binary Exograph's cli tool takes care of everything from building the app, migrating schema, and running integration tests to acting as a development server. It also simplifies deployment to cloud platforms, as we will see shortly.
Running an Exograph application requires that you build the app using exo build
and then run the server using exo-server
. The exo build
command processes the index.exo
file (and any files imported from it) and bundles JS/TS files. The result is an intermediate representation file: index.exo_ir
.
exo build
The exo-server
binary' is the runtime, whose sole purpose is to run Exograph apps. It processes the index.exo_ir file and runs the server.
exo-server
Please see the Exograph Architecture for more details.
These tools are available as Docker images, making it easy to integrate with cloud platforms and form the core of our Railway integration.
Railway Integration
The exo deploy railway
command generates a Docker file (Dockerfile.railway
) and railway.toml
to point to this file. The generated Docker file contains two stages:
- Build stage: Build the app and another to run it. The build stage uses the
exo
Docker image to build the app and then copies the result to the runtime stage. The stage also runs database migrations. - Runtime stage: Runs the server. It uses the
exo-server
Docker image.
Deploying to Railway then involves:
- Pushing all the code to GitHub (or using
railway up
to push the code directly to Railway) - Creating a Railway project
- Creating a Postgres service (unless you use an external Postgres)
- Creating a new service pointing to the GitHub repo (unless you use
railway up
) - Binding environment variables for the Postgres database to the service
Let's see how this works in practice.
Creating a new Exograph project
This is easy!
exo new todo
cd todo
This creates a new project with a simple todo app and initializes Git. If you are wondering, this doesn't generate much code. Here is the entire model!
@postgres
module TodoDatabase {
@access(true)
type Todo {
@pk id: Int = autoIncrement()
title: String
completed: Boolean
}
}
If you would like, you can run exo yolo
to try it out locally.
Deploying to Railway
We have a choice of using Postgres offered by Railway or an external one. Let's look at both options.