# Installation

This extension is built from the `graph/` crate with `pgrx` 0.19.1. The crate
officially supports PostgreSQL 14 through 18 and defaults to `pg17`. A legacy
`pg13` pgrx feature remains available on a best-effort basis because pgrx
still exposes it, but PostgreSQL 13 has reached upstream EOL and is not part of
the release support matrix.

<Callout type="info">
Official pgGraph 1.1.0 packages support PostgreSQL 14 through 18.
</Callout>

## Source Build Requirements

These requirements apply to PGXN, manual source, and direct `cargo-pgrx`
installs. Homebrew and Docker installs do not require installing Rust or pgrx
separately.

| Requirement | Version or note |
|---|---|
| Rust | `1.96`, pinned by `graph/rust-toolchain.toml` |
| PostgreSQL | 14, 15, 16, 17, or 18, with server development headers and `pg_config` |
| pgrx | `0.19.1` |
| Crate feature | One of `pg14`, `pg15`, `pg16`, `pg17`, `pg18` |
| Extension control | `graph/graph.control` |

<Callout type="info">
Install with the PostgreSQL major that matches the target server. A `pg17`
build should not be installed into a PostgreSQL 16 server.
</Callout>

## Homebrew Install

The [Evokoa Homebrew tap](https://github.com/Evokoa/homebrew-tap) provides the
PostgreSQL 17 convenience formula.

```bash
brew tap Evokoa/tap
brew install pggraph
brew test pggraph
```

Create and verify the extension in a local database:

```bash
brew services start postgresql@17
psql -d postgres -c "CREATE EXTENSION graph;"
psql -d postgres -c "SELECT extname, extversion FROM pg_extension WHERE extname = 'graph';"
```

The formula installs pgGraph 1.1.0 from the signed release bundle.

The Homebrew formula is a convenience channel for PostgreSQL 17. The complete
1.1 package matrix is the checksummed PGXN/source archive and attested GHCR
images for PostgreSQL 14 through 18.

Homebrew is maintained through the separate Evokoa tap, not published by this
repository's protected PGXN/GHCR workflow. The tap owner updates its source URL
and checksum from the signed release bundle, runs the formula audit and test,
and announces availability only after the installed extension reports 1.1.0.

## Install pgrx

Install cargo-pgrx and register the PostgreSQL on your `PATH` with pgrx. The
major is detected from `pg_config`:

```bash
cargo install cargo-pgrx --version 0.19.1 --locked
PG_MAJOR=$(pg_config --version | sed -E 's/[^0-9]*([0-9]+).*/\1/')
cargo pgrx init --pg${PG_MAJOR}="$(which pg_config)"
```

To register a different installation, point the flag at that server's
`pg_config`. For example, a Debian or Ubuntu PostgreSQL 16 install:

```bash
cargo pgrx init --pg16=/usr/lib/postgresql/16/bin/pg_config
```

For PostgreSQL 13, use the legacy `pg13` pgrx feature only as best-effort
compatibility. It is not covered by release gates after PostgreSQL 13 upstream
EOL.

## PGXN Source Install

PGXN serves the exact checksummed source ZIP from the signed 1.1.0 release
bundle. Because pgGraph is a Rust/pgrx extension, source installation requires
Rust and `cargo-pgrx` before running `pgxn install`.

```bash
cargo install cargo-pgrx --version 0.19.1 --locked
# Register the installed PostgreSQL with pgrx (auto-detects the major):
PG_MAJOR=$(pg_config --version | sed -E 's/[^0-9]*([0-9]+).*/\1/')
cargo pgrx init --pg${PG_MAJOR}="$(which pg_config)"
pgxn install pgGraph
```

## Manual Source Install

Compile and install the extension from source:

```bash
git clone https://github.com/evokoa/pggraph.git
cd pggraph
make install # may need sudo
```

If your machine has multiple PostgreSQL installations, set `PG_CONFIG` to the
target server's `pg_config`, then re-run the installation:

```bash
export PG_CONFIG=/usr/lib/postgresql/17/bin/pg_config
make install
```

If `sudo` is needed for `make install`, preserve `PG_CONFIG`:

```bash
sudo --preserve-env=PG_CONFIG make install
```

If compilation fails with `fatal error: postgres.h: No such file or directory`,
install the PostgreSQL server development package for the target PostgreSQL
major, such as `postgresql-server-dev-17` on Ubuntu or Debian.

## Build And Install With cargo-pgrx

`make install` wraps this flow. To run it directly, build with the feature that
matches your `pg_config` major and install into that server:

```bash
cd graph
PG_MAJOR=$(pg_config --version | sed -E 's/[^0-9]*([0-9]+).*/\1/')
cargo pgrx install --no-default-features --features pg${PG_MAJOR} --pg-config="$(which pg_config)"
```

To target a different installation, set its `pg_config` explicitly. For example,
a Debian or Ubuntu PostgreSQL 16 install:

```bash
cd graph
cargo pgrx install --no-default-features --features pg16 --pg-config=/usr/lib/postgresql/16/bin/pg_config
```

## Create The Extension

```sql
CREATE EXTENSION graph;
```

The extension creates the public `graph` functions and types documented in the
[API Reference](./api-reference), together with extension-owned catalogs used
to retain registrations, jobs, and synchronization state. Treat every
underscore-prefixed object as internal; applications should use documented
public functions rather than reading or writing those catalogs directly.

## Docker Install Options

pgGraph supports three Docker installation paths:

| Path | Use when |
|---|---|
| Pull the pre-built image from GHCR | You want the fastest start with no build step |
| Build a PostgreSQL image with pgGraph already installed | You want a new container image for Evokoa or local evaluation |
| Install into an existing running PostgreSQL container | You already have a PostgreSQL container and want to add pgGraph to it |

### Pre-built Docker Image

Attested images are available on GitHub Container Registry for PostgreSQL 14
through 18 and support **linux/amd64** and **linux/arm64**.

```bash
docker pull ghcr.io/evokoa/pggraph:1.1.0
```

| Tag | Description |
|---|---|
| `1.1.0` | Pinned reproducible tag (PostgreSQL 17) — always resolves to the same image digest |
| `latest` | Moving tag that points to the most recent stable PostgreSQL 17 image |
| `pg14-1.1.0` through `pg18-1.1.0` | Versioned image for a specific PostgreSQL major |
| `pg14` through `pg18` | Latest stable image for a specific PostgreSQL major |

Start the container:

```bash
docker run --rm \
  -e POSTGRES_PASSWORD=postgres \
  -e POSTGRES_DB=graph \
  -p 5432:5432 \
  ghcr.io/evokoa/pggraph:1.1.0
```

Verify that `pg_cron` and `graph` are installed and loaded:

```bash
psql -h localhost -U postgres -d graph -c "SELECT extname, extversion FROM pg_extension WHERE extname IN ('pg_cron','graph');"
```

The default image includes PostgreSQL 17, `pg_cron`, and pgGraph. Use the
`pg14-*` through `pg18-*` tags when you need a specific PostgreSQL major. On
first initialization, `docker/init/01-create-extensions-and-schedule.sql`
creates the `pg_cron` and `graph` extensions and schedules
`graph.run_scheduled_maintenance()` every five minutes. For databases beyond
the initial Docker database, create the extension explicitly with
`CREATE EXTENSION graph;`.

### Build A PostgreSQL Image With pgGraph

From the repository root, build the root `Dockerfile` with the PostgreSQL major
that should be installed in the image:

```bash
docker build --build-arg PG_MAJOR=17 -t pggraph-postgres:17 .
```

Start the container:

```bash
docker run \
  --name pggraph-postgres \
  -e POSTGRES_PASSWORD=postgres \
  -e POSTGRES_DB=graph \
  -p 5432:5432 \
  pggraph-postgres:17
```

The root Docker image starts PostgreSQL with `pg_cron` and `graph` in
`shared_preload_libraries`, runs
`docker/init/01-create-extensions-and-schedule.sql` on first database
initialization, and creates:

| Object | Purpose |
|---|---|
| `pg_cron` extension | Enables cron-style scheduling inside the Docker database |
| `graph` extension | Installs pgGraph in the Docker database |
| `pggraph-maintenance` cron job | Runs `graph.run_scheduled_maintenance()` every five minutes |

The init SQL runs only when PostgreSQL initializes a new data directory. If you
reuse an existing Docker volume, recreate the volume before expecting init SQL
changes to apply.

For databases beyond the initial Docker database, create the extension
explicitly:

```sql
CREATE EXTENSION graph;
```

### Install Into An Existing PostgreSQL Container

Use the helper script from the repository root:

```bash
scripts/install_into_docker_postgres.sh CONTAINER [PG_MAJOR] [DB_NAME] [DB_USER]
```

For example, to install pgGraph built for PostgreSQL 17 into a running container
named `my-postgres` and create the extension in `appdb`:

```bash
scripts/install_into_docker_postgres.sh my-postgres 17 appdb postgres
```

The one-shot script builds the matching pgGraph package, copies the extension
control, SQL, and shared library files into the target container, and runs:

```sql
CREATE EXTENSION IF NOT EXISTS graph;
```

The lower-level steps are also available when you want to build once and install
the same package into one or more containers:

```bash
scripts/build_docker_pggraph_package.sh 17 target/docker-packages
scripts/copy_pggraph_package_to_docker_postgres.sh \
  my-postgres target/docker-packages/graph-pg17 17 appdb postgres
```

To build packages for all supported PostgreSQL majors:

```bash
scripts/build_docker_pggraph_package.sh all target/docker-packages
```

Set `SKIP_CREATE_EXTENSION=1` to copy the files without creating the extension:

```bash
SKIP_CREATE_EXTENSION=1 scripts/install_into_docker_postgres.sh my-postgres 17
```

<Callout type="warning">
The PostgreSQL major must match the target container. A PostgreSQL 17 pgGraph
build should not be copied into a PostgreSQL 16 container. The target container
also needs compatible operating-system and CPU architecture assumptions for the
compiled extension.
</Callout>

## shared_preload_libraries

Most functionality works without `shared_preload_libraries`, but setting it lets
PostgreSQL call `_PG_init()` at server startup. `_PG_init()` registers the GUCs
and asks the operating system to pre-warm an existing `.pggraph` file.

```conf
shared_preload_libraries = 'graph'
```

Then restart PostgreSQL.

<Callout type="info">
Pre-warming does not load the engine in every backend. Query backends still load
the graph lazily on first use when `graph.auto_load = true`.
</Callout>

## Verify Installation

```sql
SELECT extname, extversion FROM pg_extension WHERE extname = 'graph';
SELECT * FROM graph.status();
```

Expected initial state before build:

| Column | Typical value |
|---|---|
| `node_count` | `0` |
| `edge_count` | `0` |
| `sync_mode` | `trigger` unless configured |
| `schema_status` | `current` |

Package, PostgreSQL-major, security, and release validation procedures are
maintainer workflows. Contributors can run them from the
[Testing And Release](../contributor_guide/testing-release) guide.

## Upgrading and Migration

The alpha-to-1.0 boundary is a source-preserving clean install and rebuild. It
does not promise in-place compatibility for alpha extension catalogs or graph
artifacts. Follow the [pgGraph 1.0 Migration Guide](./migration-1-0) before
replacing the package.

### Global Catalog Registration

Earlier alpha versions used a single global registration catalog. Do not copy
those extension-owned rows into 1.0. Record the reviewed source mappings before
upgrade, install 1.0 cleanly, and reapply registrations through public
`graph.add_table()`, `graph.add_edge()`, and `graph.add_filter_column()` calls.
Calls that omit a named graph target the 1.0 default graph.

### Artifact Path Migration

Each graph has an artifact root at
`$PGDATA/<graph.data_dir>/<graph_id>/`. The `graph_id` is the stable directory
key; graph name and namespace stay in PostgreSQL catalogs rather than the
filesystem path.

`main.pggraph` remains the logical compatibility path and the fallback for a
legacy store without projection metadata. Current persisted builds write an
immutable `projection-generation-<generation>-base.pggraph` file, publish its
checksummed `projection-generation-<generation>.json` manifest, and then
atomically switch `projection-current.json`. Loaders follow that current
pointer and manifest instead of assuming that `main.pggraph` is the serving
file. If you inspect artifacts directly, inspect the graph-id directory and
resolve the current manifest rather than selecting the highest-numbered file.

### Projection Generation Migration

Alpha projections are derived state and do not continue serving across this
boundary. Rebuild them from the authoritative PostgreSQL source tables after
the 1.0 registrations have been applied.

### Rollback and Repair Guidance

If validation fails, stop before directing application traffic to the new
extension and restore the pre-upgrade database/package pair.

**To recover:**
1. **Restore the backup** into a clean database using the same alpha package.
2. **Retry the 1.0 clean install** only after correcting the failed preflight.
3. **Reapply reviewed registrations and rebuild** from PostgreSQL source tables.
4. **Remove old derived artifacts only after validation** confirms the rebuilt
   1.0 graph is healthy.
