Article illustration 1

For developers orchestrating complex data workflows, the boundary between database logic and external services often creates friction. Enter pgsql-http, a PostgreSQL extension that shatters this barrier by embedding HTTP client capabilities directly into the database engine. This tool transforms SQL from a data query language into a gateway for web interactions—enabling triggers that ping microservices, stored procedures that consume APIs, and real-time data enrichment without middleware.

Beyond Simple GET Requests

While basic HTTP GET functionality is table stakes, pgsql-http offers nuanced control:

-- Authenticated API call with headers
SELECT content::json->'headers'->>'Authorization' 
FROM http(('GET', 'https://api.example.com', 
           http_headers('Authorization','Bearer token'), 
           NULL, NULL)::http_request);

Key features include:
- Full HTTP Method Support: GET, POST, PUT, PATCH, DELETE, and HEAD
- Structured Request/Response Objects: Native http_request and http_response composite types
- Header Management: Array-based http_header tuples for precise control
- Binary Payload Handling: text_to_bytea() for processing images, files, or protobufs
- Dynamic Parameterization: JSONB payloads for POST/PUT requests

The Architecture Underneath

Every operation revolves around two core composite types:

http_request (
  method http_method,
  uri VARCHAR,
  headers http_header[],
  content_type VARCHAR,
  content VARCHAR
)

http_response (
  status INTEGER,
  content_type VARCHAR,
  headers http_header[],
  content VARCHAR
)

Convenience wrappers like http_get() or http_post() abstract these types, but power users can construct raw requests for advanced scenarios. Header arrays can be destructured with unnest(), allowing granular inspection of responses.

Production-Grade Configuration

Serious deployments require tuning:

-- Set connection timeout to 200ms
SET http.curlopt_timeout_msec = 200; 

-- Enable TCP keep-alive for performance
SET http.curlopt_tcp_keepalive = 1;  

-- Identify requests for abuse monitoring
SET http.curlopt_useragent = 'MyApp/1.0 (+http://myapp.com/contact)';

The extension exposes 30+ libcurl options, including proxies, TLS authentication, and DNS settings—configurable per connection, role, or database.

Why Proceed with Caution?

While compelling, database-triggered HTTP calls introduce risks:

"What if the web page takes a long time to return? Your SQL call will just wait there until it does. Make sure your web service fails fast."
— Extension documentation

Critical considerations:
1. Blocking Operations: HTTP calls execute synchronously, potentially freezing database sessions.
2. Error Handling: Malformed responses or timeouts require explicit SQL-side validation.
3. Security: Exposing HTTP in triggers could enable SSRF attacks or accidental DDoS.
4. Resource Consumption: Each request consumes connections; runaway triggers could exhaust sockets.

Mitigations include aggressive timeouts (set via curlopt_timeout_ms), using pg_cron for async execution, and strict function permission controls.

Practical Use Cases

When used judiciously, pgsql-http enables powerful patterns:
- Real-Time Enrichment: Augment user profiles via API on INSERT
- Webhook Triggers: Notify external systems on data changes
- Microservice Orchestration: Chain database operations with service calls in transactions
- Data Hydration: Pull external datasets directly into temp tables

Getting Started

For Debian-based systems:

apt install postgresql-17-http  # Replace 17 with your PG version

Then in PostgreSQL:

CREATE EXTENSION http;

-- Test connectivity
SELECT status FROM http_get('https://httpbun.com');

The Delicate Power

pgsql-http exemplifies PostgreSQL's extensibility, turning the database into an active participant in distributed systems. Yet this power resembles a sharp knife: invaluable for precise tasks, dangerous when mishandled. Developers must weigh the convenience of in-database HTTP against PostgreSQL's core strengths—and remember that some boundaries exist for good reason. When APIs meet ACID, proceed with both ambition and humility.