# Without pgvector

Vectors need PostgreSQL with the pgvector extension, which the major
hosted services offer. There is no fallback: a search held anywhere else
would behave differently from the one you tested.

- **The first migration with a vector column** creates the extension
  (`CREATE EXTENSION IF NOT EXISTS "vector"`). An app with no vector
  never needs pgvector, as one with no geometry never needs PostGIS
  ([Geospatial](geospatial.md)).
- **A server without pgvector.** `jadpo migrate apply`, and `jadpo dev`
  and `jadpo test` as they migrate, check `pg_available_extensions` for
  every extension a pending migration creates, before running anything.
  A missing one is `migration.extension_missing`
  ([Command errors](command-errors.md)), the same error
  geospatial apps get. Whether the database role may create the
  extension is found when the migration runs:

  ```text
  error: `main` has no `vector` extension
    reason: `vector` is pgvector, which stores and searches the project's vectors; there is no fallback, since a search held anywhere else would behave differently from the one that was tested. The project's migrations create it, and its database server neither has it nor offers it, so nothing was applied.
    next: Install pgvector on the database server, or use a server that has it (the major hosted services do), then run the command again (human)
    rule: migration.extension_missing
    help: https://jadpo.dev/docs/errors/migration.extension_missing
  ```

- **At start-up,** the app reads `pg_extension` and refuses a store that
  lacks an extension one of its applied migrations created, with the
  same error. `jadpo dev` runs this check after migrating.
- **pgvector 0.8.0 for an HNSW index.** A store whose migrations build
  an HNSW index, derived for a `nearest` query or declared, needs
  pgvector 0.8.0 or later. The query turns on iterative scans, and an
  older pgvector rejects `hnsw.iterative_scan` as a parameter it doesn't
  know, so the query would fail on its first call. An app with vectors
  but no HNSW index keeps working on pgvector 0.7. `jadpo migrate apply`,
  `jadpo dev` and `jadpo test` check the version the server offers before
  running a pending migration that builds one. That is
  `pg_available_extensions.default_version`, the library the server
  loads, not the version a database last installed. The start-up check
  checks it for an applied one. An older pgvector is refused with
  `migration.extension_outdated`
  ([Command errors](command-errors.md)):

  ```text
  error: `main` has pgvector 0.7.0, and its nearest-neighbour queries need 0.8.0
    reason: The project's migrations build an HNSW index for a `nearest` query, which runs with pgvector's iterative index scans so a filtered search still fills its limit; they came in pgvector 0.8.0, and the database server offers 0.7.0, so nothing was applied.
    next: Upgrade pgvector on the database server to 0.8.0 or later (the major hosted services offer it), then run the command again (human)
    rule: migration.extension_outdated
    help: https://jadpo.dev/docs/errors/migration.extension_outdated
  ```

- **Other stores.** A vector field on a store that isn't PostgreSQL,
  such as Redis or D1, is `data.vector_store_unsupported`.
- **On your machine,** `jadpo dev` and `jadpo test` start a disposable
  PostgreSQL from the machine's own tools, which need pgvector: 0.8.0 or
  later once a query uses `nearest`. Postgres.app ships 0.7.0; a package
  manager's `pgvector` adds it. The live tests that need 0.8.0 skip on an
  older server, saying so, and fail instead under CI.
- **Jadpo's own CI** runs `tools/fixtures/postgres/Dockerfile`: the
  official `postgres:16.14-bookworm` pinned by digest, with
  `postgresql-16-pgvector` 0.8.7 and `postgresql-16-postgis-3` 3.6.4 from
  apt.postgresql.org at exact versions. Nothing is installed on top of
  the `postgis/postgis` 16 images, because they are built on Debian
  bullseye, whose support has ended.
