Skip to content

Railway pgvector Runtime

Railway’s standard PostgreSQL service image does not include pgvector. Railway’s docs direct teams to use a pgvector-capable template or custom database image when an extension is not available in the standard Postgres image:

The platform expects PostgreSQL 16 plus pgvector for vector-backed candidate embedding search. The local Docker runtime is pgvector/pgvector:pg16 to match that requirement. Candidate semantic search currently stores durable vectors in CandidateProfileEmbedding.vectorJson and uses the pgvector column only as a rebuildable acceleration path for Ollama nomic-embed-text embeddings at 768 dimensions.

Do not delete the Railway database volume, reset the database, or recreate rows manually.

  1. Confirm the current Railway database major version is PostgreSQL 16. If it is not PostgreSQL 16, take a Railway backup/snapshot and use a normal PostgreSQL backup/restore or major-version upgrade path instead of reusing the volume directly.

  2. Capture a Railway backup or snapshot and keep it until the application is healthy after deployment.

  3. Capture a data baseline against the existing Railway database:

    Terminal window
    DATABASE_URL="$RAILWAY_DATABASE_URL" pnpm --filter @repo/database validate:pgvector -- --mode=baseline --output=railway-pgvector-baseline.json
  4. Change the Railway database service source to a pgvector-capable PostgreSQL 16 runtime, preferably pgvector/pgvector:pg16 or the Railway-supported pgvector template equivalent. Keep the existing volume mounted at /var/lib/postgresql/data.

  5. Redeploy the database service and wait for it to accept connections.

  6. Enable and verify pgvector while comparing existing data to the baseline:

    Terminal window
    DATABASE_URL="$RAILWAY_DATABASE_URL" pnpm --filter @repo/database validate:pgvector -- --mode=post-change --compare=railway-pgvector-baseline.json --output=railway-pgvector-post-change.json
  7. Run deploy migrations:

    Terminal window
    DATABASE_URL="$RAILWAY_DATABASE_URL" pnpm run db:migrate
  8. Smoke-test API reads for existing candidates and job postings before removing the backup/snapshot.

Run Ollama as a separate Railway service rather than inside the API container.

  1. Add an ollama service in the same Railway project and environment as the API.

  2. Configure the service to run Ollama on port 11434 with persistent storage for pulled models.

  3. Pull nomic-embed-text before enabling the API provider, for example from a Railway shell on the Ollama service:

    Terminal window
    ollama pull nomic-embed-text
  4. Confirm the API service can reach the private Railway service URL from inside Railway networking.

  5. Configure optional API variables in staging first:

    Terminal window
    EMBEDDING_PROVIDER=ollama
    EMBEDDING_MODEL=nomic-embed-text
    OLLAMA_BASE_URL=http://ollama.railway.internal:11434

    Use the actual private Railway DNS name if it differs.

  6. Deploy the API and database migrations, then regenerate embeddings:

    Terminal window
    railway ssh --service api --environment prod -- pnpm --filter api candidate-embeddings:backfill

Run the same sequence in staging before production. For production, take a Railway Postgres backup or snapshot before the pgvector dimension migration, keep it through API health checks, candidate reads, job-posting reads, and suggestion refresh verification, then remove it only after the rollout is stable.

The validation report records:

  • PostgreSQL server version and current schema.
  • Whether CREATE EXTENSION IF NOT EXISTS vector succeeded.
  • Whether pg_extension contains vector.
  • Row counts for critical platform tables.
  • A full-table checksum for each critical table.
  • Five sampled primary keys per table.

For the runtime change to pass, the post-change report must show vectorExtension.enabled: true, no comparison mismatches, and unchanged row counts/checksums for the baseline tables.