Skip to content
Postgres extensions

PostgreSQL extensions

Need similar-document search, a background queue, or location queries? PostgreSQL extensions let those capabilities live beside your application data. Rent lets you declare them in RSL and use their types and operations from Rust.

For example, pgvector adds an embedding to a post and lets you find nearby posts:

datasource db {
  provider = "postgresql"
}

extension vector {
  name = "vector"
}

model Post {
  id        BigInt           @id
  title     String
  embedding pgvector.Vector? @db.Vector(1536)
}

After generating the client and applying the migration, the query looks like an ordinary post query:

let posts = client
    .post()
    .order_by_embedding_cosine(&query_vector)?
    .limit(10)
    .all()
    .await?;

The pgvector guide shows dependencies, vector creation, and deployment requirements.

Choose a capability

Each guide explains what the extension does, when to use it, its Rent API, and what the database server needs.

Register a pack when using its API

A pack makes an extension's types and operations available to Rent. For direct pack APIs, register it during application setup and keep the returned handle:

use rent_ext_pgvector::PgVector;

let mut extensions = rent::extension::ExtensionRegistry::default();
let pgvector = extensions.register_pack::<PgVector>()?;

That handle gives access to the extension's functions, types, operators, indexes, migrations, and higher-level clients. Pack manifests describe PostgreSQL compatibility, installation schemas, privileges, preload libraries, dependencies, provider enablement, and supported upgrade paths.

Operational extensions such as pgmq provide async clients bound to a database. Query-oriented extensions provide typed expressions that compose with Rent's query expressions and generated filters.

Share an application transaction

Pass the generated client to a registered pack to use its connection context. Inside a transaction closure, pass tx so application writes and extension calls commit or roll back together:

use rent_ext_pgmq::{Pgmq, PgmqClientExt};

let pgmq = extensions.register_pack::<Pgmq>()?;

client
    .transaction_app(async |tx| -> anyhow::Result<()> {
        let post = tx
            .create_post()
            .title("A new post")
            .body("Hello!")
            .published(false)
            .author_id(author_id)
            .save()
            .await?;

        pgmq
            .client(&tx.system())
            .queue("post_events")
            .send(serde_json::json!({ "post_id": post.id }))
            .await?;

        Ok(())
    })
    .await?;

Create the queue during application setup. A registered pack can also bind directly to a DatabasePool for independent operations. Binding to a transaction client preserves its connection and session settings. Using that client after commit or rollback returns a closed-transaction error. Database row-level security still applies. Arbitrary extension SQL does not infer Rent entity policies or the tenant guard, so a generated client must be a system handle (tx.system() keeps the transaction) or calls return DriverError::RawSqlRequiresSystem. Check application authorization before issuing administrative calls or enqueueing privileged work.

Scalar and row-set results

The shared extension client decodes native SQL values. query_i32, query_i64, query_string, query_bytes, query_f32, query_f64, and query_bool return None for no row or SQL NULL and reject multiple rows. Use query_scalar_result::<T> when you need to distinguish ScalarResult::NoRow, ScalarResult::Null, and ScalarResult::Value(value). query_required::<T> requires one non-NULL value. Type mismatches are errors, not automatic coercions. SQL NULL and the JSON value null remain distinct in typed JSON scalar results.

Use query_json for row sets and execute for operations whose result is intentionally ignored.

Prepare the database server

Before planning an extension migration, verify the destination server and hosting policy:

rent extension check --provider self-hosted

After installation or upgrade, inspect the versions and database objects that are actually present:

rent extension status

Both commands support --format json for deployment automation. See the check and status command guides for full output and provider options.