Skip to content

pg_lease

SQL leases with TTL expiry and monotonically increasing fencing epochs

Overview

PackageVersionCategoryLicenseLanguage
pg_lease0.1.0UTILMITSQL
IDExtensionBinLibLoadCreateTrustRelocSchema
4145pg_leaseNoNoNoYesYesNolease

PGXN testing release. Requires PG14+; upstream tests PG14/15, local EL9 aarch64 regression and isolation tests pass PG14-18. No failover fencing guarantee; owner strings are application identities. PGXN-listed GitHub repository azghr/pg-primitive returned 404 on 2026-10-23; PGXN hosts the verified source.

Version

TypeRepoVersionPG VerPackageDeps
EXTPIGSTY0.1.01817161514pg_lease-
RPMPIGSTY0.1.01817161514pg_lease_$v-
OS / PGPG18PG17PG16PG15PG14
el8.x86_64
el8.aarch64
el9.x86_64
el9.aarch64
el10.x86_64
el10.aarch64
d12.x86_64N/AN/AN/AN/AN/A
d12.aarch64N/AN/AN/AN/AN/A
d13.x86_64N/AN/AN/AN/AN/A
d13.aarch64N/AN/AN/AN/AN/A
u22.x86_64N/AN/AN/AN/AN/A
u22.aarch64N/AN/AN/AN/AN/A
u24.x86_64N/AN/AN/AN/AN/A
u24.aarch64N/AN/AN/AN/AN/A
u26.x86_64N/AN/AN/AN/AN/A
u26.aarch64N/AN/AN/AN/AN/A

Build

You can build the RPM packages for pg_lease using pig build:

pig build pkg pg_lease         # build RPM packages

Install

You can install pg_lease directly. First, make sure the PGDG and PIGSTY repositories are added and enabled:

pig repo add pgsql -u          # Add repo and update cache

Install the extension using pig or apt/yum/dnf:

Install
pig install pg_lease;          # Install for current active PG version
pig
pig ext install -y pg_lease -v 18  # PG 18
pig ext install -y pg_lease -v 17  # PG 17
pig ext install -y pg_lease -v 16  # PG 16
pig ext install -y pg_lease -v 15  # PG 15
pig ext install -y pg_lease -v 14  # PG 14
dnf
dnf install -y pg_lease_18       # PG 18
dnf install -y pg_lease_17       # PG 17
dnf install -y pg_lease_16       # PG 16
dnf install -y pg_lease_15       # PG 15
dnf install -y pg_lease_14       # PG 14

Create Extension:

CREATE EXTENSION pg_lease;

Usage

Sources:

pg_lease provides expiring ownership of named resources with increasing fencing epochs. It is a pure SQL/PL/pgSQL extension with lazy expiry, no background worker, and no preload requirement. Version 0.1.0 is marked testing on PGXN; upstream requires PostgreSQL 14 or later and documents its compatibility tests on PostgreSQL 14 and 15.

Core Workflow

The extension is trusted: a role with CREATE privilege on the database can install it. It creates the fixed lease schema and is not relocatable.

CREATE EXTENSION pg_lease;

SELECT acquired, epoch, expires_at
FROM lease.acquire('job-42', 'worker-a', interval '30 seconds');

SELECT status, expires_at
FROM lease.renew('job-42', 'worker-a', 1, interval '30 seconds');

SELECT status FROM lease.release('job-42', 'worker-a', 1);
SELECT held, owner, epoch, expires_at FROM lease.inspect('job-42');

The example uses the first epoch, 1. Applications must pass the epoch actually returned by acquisition to later renewal, release, and external resource guards. A successful release advances the epoch; re-acquisition must use the newly returned value.

Operations

OperationBehavior
lease.acquire(key, owner, ttl, wait)Acquires a free or expired key. The optional wait defaults to zero; a busy key returns a denial. Positive waits poll until acquisition or timeout.
lease.renew(key, owner, epoch, ttl)Extends an active lease without changing its epoch.
lease.release(key, owner, epoch)Releases an active lease and advances its epoch.
lease.inspect(key)Observes ownership, expiry, and the current fencing counter; an unknown key returns no rows.

Renewal and release return ok, not_owner, lapsed, or epoch_mismatch. Invalid inputs raise SQLSTATE 22023; an exhausted blocking wait raises 57014. Re-acquiring an unexpired lease with the same owner is idempotent and does not extend its expiry.

Transactions and Boundaries

Use READ COMMITTED for blocking acquisition. State changes follow the caller’s transaction and are undone by rollback. Expiry follows the database server’s clock; session termination does not release a lease immediately. The functions use SECURITY DEFINER with a fixed search path; direct public access to lease.leases is revoked.

Owner strings are application-supplied identifiers, not authenticated database identities. Applications must control access to the lease API and enforce fencing epochs at the resource being protected. The extension provides no safety guarantee across primary promotion or independent databases. Dropping the extension destroys lease state and resets the epoch history on reinstallation; version 0.1.0 does not register its lease table for extension configuration dumps.

Was this page helpful?