Skip to Content

Neo4j provisioning (timelining)

Timelining stores graph data (entries, embeddings, visualise APIs) in Neo4j Community Edition, hosted on Railway. Propagate provisions Neo4j automatically during propagate apply unless you override credentials in .propagate/values.yaml.

Why Neo4j on Railway?

Timelining runs on Vercel (serverless). Neo4j requires a persistent database with Bolt protocol access. Railway hosts the database as a separate service, built from the timelining repo’s .docker/ directory, with a TCP proxy so Vercel can connect over bolt://.

Default operator flow

  1. propagate create — no Neo4j prompts. Info log states Neo4j will be provisioned on apply.
  2. propagate auth railway — one-time: save Railway API token to .propagate/credentials.json.

Railway API token requirements

Create the token at railway.com/account/tokens  with “No workspace” selected in the scope dropdown.

Token scopeWorks with propagate?
No workspace (account token)Yes — required for { me } probe and project listing
Workspace-scoped tokenNo — returns “Not Authorized” on GraphQL probe

Propagate sends Authorization: Bearer <token> to https://backboard.railway.com/graphql/v2. Project tokens (RAILWAY_TOKEN from railway link) use a different header and are not supported.

Verify your token:

curl -X POST https://backboard.railway.com/graphql/v2 \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"query\":\"query { me { id } }\"}"

A successful response includes "data": { "me": { "id": "..." } }.

  1. Railway ↔ GitHub — link your Railway account to the target GitHub org (same org as stack.yamlprovider.github.targetOrg) so Railway can build from the forked timelining repo.
  2. propagate validate — resolves neo4j.connection as provisioned; validates .docker/Dockerfile exists in the timelining repo.
  3. propagate apply — Pulumi:
    • Forks timelining (includes .docker/)
    • Deploys timelining to Vercel
    • Creates or reuses Railway service {deploymentSlug}-timelining-neo4j
    • Builds from fork repo rootDirectory: .docker
    • Enables TCP proxy on port 7687
    • Injects NEO4J_URI, NEO4J_USERNAME, NEO4J_PASSWORD into the timelining Vercel project

Docker image location

The Neo4j image definition lives in the timelining repo at .docker/:

FilePurpose
.docker/DockerfileExtends neo4j:5-community with timelining config
.docker/neo4j.confBolt, memory, vector index settings

The timelining app.manifest.yaml declares:

- id: neo4j.connection source: provisioned provisioner: railway.neo4j dockerPath: .docker

Override with your own Neo4j

Add to .propagate/values.yaml to skip Railway provisioning:

capabilities: neo4j.connection: NEO4J_URI: bolt://your-host:7687 NEO4J_USERNAME: neo4j NEO4J_PASSWORD: your-password

Re-run propagate validate before apply.

Existing Railway instance

If propagate apply detects an existing timelining or Neo4j service in your Railway account (and no neo4j.connection override in values), the CLI prompts for NEO4J_URI, NEO4J_USERNAME, and NEO4J_PASSWORD — the same manual workflow as before auto-provisioning.

Idempotency

  • Railway service name: {deploymentSlug}-timelining-neo4j
  • Railway project name (if not set in stack): {deploymentSlug}-propagate
  • Re-running propagate apply reuses the same Pulumi-managed service; it does not create duplicate instances.

Optional: set provider.railway.projectId in stack.yaml to target a specific Railway project.

Troubleshooting

IssueRemedy
RAILWAY_API_TOKEN is requiredRun propagate auth railway
Not Authorized on Railway probeCreate token with No workspace at railway.com/account/tokens; unset shell RAILWAY_TOKEN if set
Railway build failsEnsure Railway GitHub App is linked to target org; fork contains .docker/Dockerfile
No TCP proxy / connection timeoutCheck Railway service networking → TCP proxy on port 7687
Invalid bolt URIUse bolt://host:port (timelining uses encryption off for Railway proxy)
Service exists but credentials unknownAdd neo4j.connection to values.yaml or destroy the Railway service
Last updated on