Deploying to Production
Pastoria apps are Node.js servers. After building, you deploy the output to any platform that runs Node.js.
Build the app
# Run code generation and build
pnpm generate
pnpm build
This produces two directories:
dist/client/— optimized JavaScript, CSS, and assets for the browserdist/server/— server-side rendering bundle for Node.js
The build also generates __generated__/router/persisted_queries.json, which
maps query IDs to query text for the GraphQL endpoint.
Start the production server
NODE_ENV=production pastoria-server
The pastoria-server binary (from the pastoria-server package) starts an
Express server on port 8000 that:
- Loads environment variables from
.envvia dotenv - Reads
dist/client/.vite/manifest.jsonfor asset fingerprinting - Reads
__generated__/router/persisted_queries.jsonfor persisted queries - Imports the compiled server entry from
dist/server/ - Serves static files from
dist/client/ - Handles SSR for all routes and the GraphQL API at
/api/graphql
Required build artifacts
These files must be present at runtime:
| Artifact | Purpose |
|---|---|
dist/client/ | Static assets served to browsers |
dist/client/.vite/manifest.json | Asset fingerprinting for preload hints |
dist/server/ | Server-side rendering bundle |
__generated__/router/persisted_queries.json | Persisted query ID to query text map |
Environment variables
Pastoria loads .env files automatically in production via dotenv. You can
use this for database credentials, API keys, or any runtime configuration your
resolvers need.
There are no Pastoria-specific environment variables. All framework
configuration is done through PastoriaEnvironment in pastoria/environment.ts
— see Configuration Reference.
Deploying with Docker
Create a Dockerfile at your project root:
FROM node:20-slim
# Enable pnpm
RUN corepack enable
WORKDIR /app
# Install dependencies
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --prod
# Copy build artifacts
COPY dist/ dist/
COPY __generated__/router/persisted_queries.json __generated__/router/persisted_queries.json
# Copy .env if needed
# COPY .env .env
ENV NODE_ENV=production
EXPOSE 8000
CMD ["npx", "pastoria-server"]
Build and run:
# Build the app locally first
pnpm generate && pnpm build
# Build and run the Docker image
docker build -t my-app .
docker run -p 8000:8000 my-app
Deploying to Fly.io
Create a fly.toml:
[build]
[http_service]
internal_port = 8000
force_https = true
[env]
NODE_ENV = "production"
Then deploy:
pnpm generate && pnpm build
fly deploy
Deploying to Railway
Railway auto-detects Node.js apps. Set these in your project settings:
- Build command:
pnpm generate && pnpm build - Start command:
NODE_ENV=production npx pastoria-server - Port:
8000
Production checklist
-
NODE_ENV=productionis set — this enables persisted-queries-only mode and disables GraphiQL -
.envfile is configured with production credentials -
pnpm generate && pnpm buildhas been run - All three required artifact paths exist (
dist/client/,dist/server/,__generated__/router/persisted_queries.json) - Port 8000 is exposed and accessible
Next steps
- Learn how server-side rendering works under the hood
- Review the configuration reference for
production settings like
persistedQueriesOnlyInProduction