Comprehensive Guide: Deploying and Debugging Custom Webhooks on Supabase & PostgreSQL

Rodrigo Mansueli - Aug 29 '23 - - Dev Community

In today's dynamic landscape of cutting-edge application development, the role of automation has grown paramount, revolutionizing user experiences and operational efficiency. A domain where automation truly thrives is the seamless integration of webhooks into your application's architecture. Webhooks introduce the power to orchestrate actions triggered by specific events within your database. This automated responsiveness gains exceptional potency when harmonized with a versatile backend service like Supabase and the robust capabilities of PostgreSQL. This comprehensive article embarks on a journey to unveil the art of creating and debugging PostgreSQL webhooks using the Supabase platform, highlighting the potent synergy that can reshape and optimize your development workflow.

The Nexus of Empowerment: An Alliance of Supabase and PostgreSQL

In the dynamic realm of modern application development, the selection of a backend service extends beyond technical considerations; it's a strategic choice with far-reaching implications for productivity and efficiency. The formidable partnership between Supabase and PostgreSQL presents a compelling proposition. This article delves into the realm of webhooks—automated triggers designed to spring into action in response to specific database events. Our journey involves an in-depth exploration of the intricacies involved in designing and debugging Postgres webhooks, harnessing the capabilities of Supabase to establish a fluid and efficient workflow.

Expanding Horizons: The Webhook Wrapper Function

At the heart of our webhook implementation, a pivotal role is played by the request_wrapper function. This versatile function operates as an intermediary, adroitly handling HTTP methods such as GET, POST, and DELETE. It forges smooth communication channels with external services and APIs, driven by dynamic input parameters encompassing method, url, params, body, and headers. Crafted using the expressive plpgsql language and fortified by the security definer concept for meticulous execution control, this function embodies the quintessence of streamlined automation.

Taking Charge of Your Automation: The Supabase Advantage

While Supabase generously offers webhooks as part of its toolkit, it is worth contemplating the merits of deploying them independently. By taking the reins of deployment, you gain the freedom to expand the timeout window beyond a mere second, granting you greater control over the nature of the requests being executed. This strategic move allows you to tailor the automation to your specific needs, resulting in a more responsive and versatile system.

-- 
-- Webhook wrapper
--
CREATE OR REPLACE FUNCTION request_wrapper(
    method TEXT,
    url TEXT,
    params JSONB DEFAULT '{}'::JSONB,
    body JSONB DEFAULT '{}'::JSONB,
    headers JSONB DEFAULT '{}'::JSONB
)
RETURNS BIGINT
SECURITY DEFINER
SET search_path = public, extensions, net
LANGUAGE plpgsql
AS $$
DECLARE
    request_id BIGINT;
    timeout INT;
BEGIN
    timeout := 3000;

    IF method = 'DELETE' THEN
        SELECT net.http_delete(
            url:=url,
            params:=params,
            headers:=headers,
            timeout_milliseconds:=timeout
        ) INTO request_id;
    ELSIF method = 'POST' THEN
        SELECT net.http_post(
            url:=url,
            body:=body,
            params:=params,
            headers:=headers,
            timeout_milliseconds:=timeout
        ) INTO request_id;
    ELSIF method = 'GET' THEN
        SELECT net.http_get(
            url:=url,
            params:=params,
            headers:=headers,
            timeout_milliseconds:=timeout
        ) INTO request_id;
    ELSE
        RAISE EXCEPTION 'Method must be DELETE, POST, or GET';
    END IF;
    RETURN request_id;
END;
$$;
Enter fullscreen mode Exit fullscreen mode

Creating a Trigger Function for Automated Insert Events

Imagine a scenario where a new row enters the picture in the orders table. This particular moment sets in motion an automatic process triggered by a special function we've named after_order_insert(). Within this function's code lies a sophisticated logic that effortlessly triggers a call to another function called request_wrapper. This dynamic function orchestrates a POST request that's directed to a specific webhook URL you define. The magic happens as the values from the newly added row come together to form a JSON package—an essential element that shapes the upcoming webhook request.

CREATE OR REPLACE FUNCTION after_order_insert()
RETURNS TRIGGER AS $$
BEGIN
    PERFORM request_wrapper('POST', 'your_webhook_url_here', 
                            '{"order_id": ' || NEW.order_id || 
                            ', "customer_id": ' || NEW.customer_id || 
                            ', "total_amount": ' || NEW.total_amount || '}');
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Enter fullscreen mode Exit fullscreen mode

Leading the Way with Triggers: Powering Automation for New Inserts

In the dynamic realm of PostgreSQL databases, the birth of triggers stands as a foundational pillar of database event automation. Our carefully crafted trigger, given the name orders_insert_webhook, steps onto the stage. This conductor is designed to harmonize with the rhythm of each fresh row that finds its place in the revered orders table. This invisible maestro then coordinates the execution of the after_order_insert() function as soon as a new data insertion event occurs. The result is a symphony of seamless coordination, allowing webhooks to come to life in response to the emergence of new data.

CREATE TRIGGER orders_insert_webhook
AFTER INSERT ON orders
FOR EACH ROW
EXECUTE FUNCTION after_order_insert();
Enter fullscreen mode Exit fullscreen mode

Exploring Webhook Debugging: A Closer Look

The journey through webhook integration entails not only implementation but also a vital debugging phase. This phase ensures the smooth functioning of your automated processes. At the core of this endeavor lies the net._http_response table—a valuable tool for debugging. This table captures the responses generated by HTTP requests executed through the request_wrapper function. It offers insights into request outcomes, including success, status codes, headers, content, timeouts, error messages, and creation timestamps.

Navigating the Debugging Process: Inside net._http_response

In your PostgreSQL database architecture, the net._http_response table takes on a crucial role. Its design encapsulates essential debugging information, aiding you in refining your automated workflows. This table serves as a repository of records detailing each HTTP request's journey. These insights are invaluable for diagnosing and resolving any issues in your automation processes. From tracking response status and content type to examining headers, content, and possible timeouts, this table becomes your compass in the journey to create robust and efficient automation.

Real-World Insight: Practical Scenarios

To understand the practicality of the net._http_response table, let's consider an example where you've set up a webhook to notify customers upon order fulfillment. As you navigate this process, the net._http_response table becomes your ally.

Use Case 1: Checking Request Status

To verify request status, execute the following query:

SELECT id, status_code, timed_out
FROM net._http_response;
Enter fullscreen mode Exit fullscreen mode

This query offers a quick overview of request details, displaying IDs, status codes, and any timeouts.

Use Case 2: Exploring Request Details

For a comprehensive view of a specific request, use:

SELECT *
FROM net._http_response
WHERE id = your_request_id_here;
Enter fullscreen mode Exit fullscreen mode

Replace your_request_id_here with the actual ID of the request. This query provides a detailed examination, including headers, content, and error messages.

In the process of webhook debugging, the net._http_response table shines as a guiding light. Its insights empower you to craft and maintain automation processes that endure.

-- Example: Checking request status
SELECT id, status_code, timed_out
FROM net._http_response;

-- Example: Exploring request details
SELECT *
FROM net._http_response
WHERE id = your_request_id_here;
Enter fullscreen mode Exit fullscreen mode

Wrapping Up: Your Path to Smarter Automation

As we come to the end of this exploration into the world of automation and efficiency in app development, it's time to reflect on the journey we've taken. Throughout this article, we've teamed up Supabase and PostgreSQL with webhooks—a powerful trio that empowers you to create smarter, more responsive applications.

If you're hungry for more insights and want to delve deeper into enhancing your Supabase-powered apps, don't forget to check out some of our previous articles:

With these resources at your fingertips, you're well-equipped to take your app development journey to new heights. Remember, the world of coding is full of possibilities, and webhooks are just the beginning. Keep innovating, keep learning, and keep coding!

Got any thoughts or questions? We'd love to hear from you. Drop a comment below and let's keep the conversation going!

🚀 Learn more about Supabase

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .