pg_net HTTP
What it is
pg_net lets PostgreSQL enqueue asynchronous HTTP and HTTPS requests. A background worker delivers GET, POST, and DELETE requests without holding the transaction open for the remote server.
What it provides
- Asynchronous HTTP requests initiated from SQL, functions, or triggers
- A request queue and response table for inspecting delivery results
- Natural composition with triggers and
pg_cron
Use it for database webhooks, notifying serverless functions after a write, synchronizing an external service, or periodically calling an internal API.
Use it with Rent
extension pg_net {
name = "pg_net"
}The RSL declaration makes installation and migration intent part of the reviewed application schema. Register the typed pack at runtime to call its APIs:
use rent_ext_pg_net::{PgNet, PgNetClientExt};
let pack = extensions.register_pack::<PgNet>()?;
let net = pack.client(&pool);
let health_request = net.get("https://example.com/health").await?;
let delivery_request = net
.post(
"https://example.com/events",
serde_json::json!({"id": 42}),
)
.await?;Application URLs and payloads are values, not interpolated SQL fragments.
A returned request ID means the request was queued, not that the destination accepted it. Requests become eligible for delivery after their transaction commits; rollback discards them. Bind the extension client to your application transaction when the webhook must follow a successful write:
let tx = client.tx().await?;
let request_id = pack
.client(&tx.client())
.post(webhook_url, serde_json::json!({"post_id": post.id}))
.await?;
tx.commit().await?;Inspect net._http_response for the HTTP status and response body. Its retention is limited, and pg_net's
queue and response tables are unlogged: this is not a durable, retrying message queue. Use a durable outbox
or pgmq when delivery must survive a database crash. Restrict destination URLs in
your application so untrusted users cannot make the database contact internal services.
Run the application
cargo run -p rent --example extension_03_pg_netSet DATABASE_URL to a disposable database with pg_net installed. The background worker's
pg_net.database_name must select that database, and pg_net.username must identify a permitted role.
Restart the worker after changing its configuration.
The application starts a temporary local HTTP receiver, queues GET and POST requests, commits, and checks the delivered method, JSON payload, status, and response body, including an HTTP 503 response after a successful enqueue. It also verifies that rolled-back and uncommitted requests are not delivered. Only synthetic tutorial data is sent, and the receiver is stopped when the application finishes.
When PostgreSQL runs in the repository's Docker profile, let its worker reach the host receiver with:
RENT_TUTORIAL_HTTP_HOST=host.docker.internal cargo run -p rent --example extension_03_pg_netFor PostgreSQL running directly on the same machine, the default receiver address is 127.0.0.1.
Its standalone extension declaration is crates/rent/examples/extension_03_pg_net/schema.rsl.