Back to Blog
Integration Guides

How to Integrate Twilio with PostgreSQL: Step-by-Step Guide

Use PostgreSQL triggers and NOTIFY with a Node.js or Python listener to send Twilio SMS when specific database events occur in your tables.

DA
Danial A
Senior Twilio Consultant, Telphi Consulting
June 22, 2026
7 min read
Twilio
Integration
Database
How to Integrate Twilio with PostgreSQL: Step-by-Step Guide

PostgreSQL and Twilio integrate through Postgres triggers that call NOTIFY to push row event data to a Node.js or Python listener process, which dispatches Twilio SMS when specific table events occur such as new order inserts, status field updates, or inventory threshold crossings. This integration is used by backend teams running self-hosted or cloud-managed PostgreSQL databases who want SMS alerting driven directly by database row events without adding a message broker or rebuilding application logic. The connection uses Postgres's native LISTEN/NOTIFY mechanism to communicate between the database and a lightweight listener service, keeping the integration close to the data layer with minimal architectural overhead.

What You Need Before You Start

Confirm your PostgreSQL version is 9.4 or higher by running SELECT version(); in psql or your database client, as the pg_notify function and reliable LISTEN/NOTIFY behavior required for this integration are stable in all modern PostgreSQL releases. Install the pg npm package in your Node.js listener project by running npm install pg twilio so both the PostgreSQL client and the Twilio SDK are available in the same listener process. Store your Twilio Account SID, Auth Token, and From Number as environment variables in a .env file loaded via dotenv in your listener application, using process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN, and process.env.TWILIO_FROM_NUMBER in your application code. From Twilio, provision an SMS-capable phone number and complete A2P 10DLC registration in the Twilio Console for US-bound messaging, and confirm the listener server has outbound HTTPS access to api.twilio.com on port 443.

Step-by-Step Integration Guide

Create a Postgres trigger function that calls pg_notify with the event channel name and a JSON payload by running: CREATE OR REPLACE FUNCTION notify_order_created() RETURNS trigger AS $$ BEGIN PERFORM pg_notify('order_created', json_build_object('id', NEW.id, 'customer_name', NEW.customer_name, 'customer_phone', NEW.customer_phone, 'total', NEW.total, 'status', NEW.status)::text); RETURN NEW; END; $$ LANGUAGE plpgsql; then attach the trigger to your orders table with: CREATE TRIGGER order_created_trigger AFTER INSERT ON orders FOR EACH ROW EXECUTE FUNCTION notify_order_created();. Write the Node.js listener that opens a persistent PostgreSQL connection, subscribes to the channel, and dispatches Twilio SMS on each notification: const { Client } = require('pg'); const twilio = require('twilio'); const dbClient = new Client({ connectionString: process.env.DATABASE_URL }); const twilioClient = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN); dbClient.connect().then(() => { dbClient.query('LISTEN order_created'); dbClient.on('notification', async (msg) => { const payload = JSON.parse(msg.payload); if (!payload.customer_phone) return; await twilioClient.messages.create({ to: payload.customer_phone, from: process.env.TWILIO_FROM_NUMBER, body: 'Hi ' + payload.customer_name + ', order #' + payload.id + ' confirmed. Total: $' + payload.total }); }); }). Create a status change trigger for the same table using the same pattern but comparing NEW.status with OLD.status and calling pg_notify only when they differ using IF NEW.status <> OLD.status THEN PERFORM pg_notify(...); END IF; inside a BEFORE UPDATE trigger. Run the listener as a persistent process using a process manager such as PM2 with pm2 start listener.js --name twilio-pg-listener to ensure the LISTEN connection is maintained and auto-restarted on crashes.

Common Issues and How to Fix Them

The PostgreSQL LISTEN connection drops silently when the database server closes idle connections due to a connection timeout policy set on the server or a cloud database proxy such as PgBouncer in transaction pooling mode, causing your listener to stop receiving notifications without any visible error in the application log. Add a keepalive mechanism to your Node.js listener by setting the keepAlive and keepAliveInitialDelayMillis options in the pg Client configuration, and add a reconnect handler on the dbClient end event that waits 5 seconds and re-establishes the connection and re-issues the LISTEN command, ensuring the listener recovers automatically from disconnections. The pg_notify function truncates payloads larger than 8,000 bytes, which can cause JSON payloads containing long text fields such as order notes or address strings to be silently truncated, resulting in malformed JSON that crashes your listener's JSON.parse call. Limit the JSON payload sent via pg_notify to only the essential fields needed for the SMS such as id, customer_phone, customer_name, and status, and have the listener make a secondary database query using the received id to fetch any additional details needed for the SMS body, keeping the NOTIFY payload small and always valid. The Node.js listener dispatches Twilio SMS synchronously inside the notification handler callback, and if the Twilio API is slow the notification queue backs up and subsequent notifications may be delayed or lost. Dispatch the Twilio SMS asynchronously by calling twilioClient.messages.create without awaiting the result inside the notification handler, and handle the promise rejection with a .catch block that logs the failure to a database error table rather than crashing the listener process.

How to Get More from This Integration

Build a Python-based listener as an alternative by using the psycopg2 library with conn.set_isolation_level(0) to enable asynchronous notification mode, then calling conn.execute('LISTEN order_created') and polling conn.poll() in a loop to receive notifications, dispatching Twilio SMS using the twilio Python package with client.messages.create(), providing a pure-Python implementation for teams already running Python application servers. Add an SMS delivery log table by creating a Postgres table named sms_log with columns id, order_id, phone, message_body, twilio_sid, status, and sent_at, and writing each Twilio API response into this table from the listener after each successful or failed dispatch, giving you a queryable record of every SMS sent that you can join against your orders table for reporting. Create a threshold alert trigger by adding a Postgres trigger on an inventory table that fires AFTER UPDATE when new_quantity < 10 and old_quantity >= 10, building the NOTIFY payload with the product name and current quantity, and having the listener dispatch a Twilio SMS to your warehouse manager's phone only when the quantity first crosses the threshold rather than on every update that keeps it below threshold. Extend the integration to a Python Django or FastAPI application by replacing the standalone listener with a Django signal or FastAPI background task that subscribes to the Postgres NOTIFY channel using an async PostgreSQL library such as asyncpg, calling asyncpg.connect() and await conn.add_listener('order_created', callback) where callback dispatches the Twilio SMS, integrating the listener directly into your existing application process.

Conclusion

PostgreSQL triggers with LISTEN/NOTIFY and Twilio together create a lightweight, reliable event-driven SMS system driven directly from your database's row-level events without any external message broker. Get in touch with Telphi Consulting to implement a PostgreSQL Twilio SMS listener tailored to your database schema and alerting requirements.

Share this article:
0 views

Ready to Transform Your Business Communications?

Get a free consultation with our VoIP experts and discover how we can help you save costs, improve efficiency, and scale your business.

Comments (0)

Join the discussion and share your thoughts (AI-moderated for quality)

Protected by AI moderation

Be the first to comment

No comments yet. Share your thoughts below.