<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Abu Bakkar Siddique</title>
    <description>The latest articles on DEV Community by Abu Bakkar Siddique (@ashraful2502).</description>
    <link>https://dev.to/ashraful2502</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4047091%2Faf6cb2f0-a7fc-4a9a-8115-45089a0ec830.png</url>
      <title>DEV Community: Abu Bakkar Siddique</title>
      <link>https://dev.to/ashraful2502</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ashraful2502"/>
    <language>en</language>
    <item>
      <title>17 Products Launched on LaunchNests This Week - Here Are 4 Worth Checking Out</title>
      <dc:creator>Abu Bakkar Siddique</dc:creator>
      <pubDate>Tue, 03 Nov 2026 06:46:20 +0000</pubDate>
      <link>https://dev.to/ashraful2502/17-products-launched-on-launchnests-this-week-here-are-4-worth-checking-out-kfc</link>
      <guid>https://dev.to/ashraful2502/17-products-launched-on-launchnests-this-week-here-are-4-worth-checking-out-kfc</guid>
      <description>&lt;p&gt;Every week, new products ship across developer tools, AI, infrastructure, and productivity. Some solve very specific problems, while others are worth watching because of the space they're building in.&lt;/p&gt;

&lt;p&gt;This week, &lt;strong&gt;17 products were launched on &lt;a href="https://www.launchnests.com/" rel="noopener noreferrer"&gt;LaunchNests&lt;/a&gt;&lt;/strong&gt;. Here are four that caught my attention.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Prisma Postgres — Managed PostgreSQL for Modern Apps
&lt;/h2&gt;

&lt;p&gt;If you're building with TypeScript, working on an AI application, or deploying a backend, your database infrastructure matters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.launchnests.com/tools/prisma-postgres-f1ed3d" rel="noopener noreferrer"&gt;Prisma Postgres&lt;/a&gt; offers managed PostgreSQL for TypeScript applications and AI agents, with built-in connection pooling and a free plan.&lt;/p&gt;

&lt;p&gt;It's worth checking out if you're looking for a managed database option for your next project.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. SiftingIO Market Data API — Financial Data for Developers
&lt;/h2&gt;

&lt;p&gt;Building anything around financial markets often means finding reliable ways to access market data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.launchnests.com/tools/siftingio-market-data-api-52b0ba" rel="noopener noreferrer"&gt;SiftingIO Market Data API&lt;/a&gt; provides real-time and historical market data through an API for developers.&lt;/p&gt;

&lt;p&gt;For anyone building financial dashboards, data-driven applications, or market analysis tools, APIs like this can be useful building blocks.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. TriRank — AI Visibility for Search Console
&lt;/h2&gt;

&lt;p&gt;Search visibility is changing as people increasingly discover information through AI-powered search experiences.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.launchnests.com/products/trirank-bb9b53" rel="noopener noreferrer"&gt;TriRank&lt;/a&gt; focuses on AI visibility for Google Search Console users.&lt;/p&gt;

&lt;p&gt;It's an interesting area to follow for developers, founders, and teams thinking about how their products get discovered online.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. TermiGram — SSH and SFTP Inside Telegram
&lt;/h2&gt;

&lt;p&gt;Sometimes, a useful product is one that brings an existing workflow into a tool you already use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.launchnests.com/products/termigram-60c10a" rel="noopener noreferrer"&gt;TermiGram&lt;/a&gt; brings SSH terminal access and SFTP file management into Telegram.&lt;/p&gt;

&lt;p&gt;If you're curious about alternative ways to access remote servers and manage files, this is one to explore.&lt;/p&gt;

&lt;h2&gt;
  
  
  More launches to discover
&lt;/h2&gt;

&lt;p&gt;These are just four highlights from this week's 17 launches. The wider batch includes products across AI video generation, productivity, and other developer and consumer tools.&lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://www.launchnests.com/" rel="noopener noreferrer"&gt;explore this week's launches on LaunchNests&lt;/a&gt; and discover something that fits your workflow—or a product that inspires your next build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building something yourself?
&lt;/h2&gt;

&lt;p&gt;If you've recently shipped a product, tool, or side project, consider submitting it to LaunchNests. It's a place to discover new products and help builders get their work in front of more people.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What caught your attention this week?&lt;/strong&gt; Share a product you think more developers should know about in the comments.&lt;/p&gt;

</description>
      <category>database</category>
      <category>startup</category>
      <category>tools</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How Batching Increased My Throughput from 342 req/s to 1,259 req/s</title>
      <dc:creator>Abu Bakkar Siddique</dc:creator>
      <pubDate>Tue, 04 Aug 2026 16:36:36 +0000</pubDate>
      <link>https://dev.to/ashraful2502/how-batching-increased-my-throughput-from-342-reqs-to-1259-reqs-4c2c</link>
      <guid>https://dev.to/ashraful2502/how-batching-increased-my-throughput-from-342-reqs-to-1259-reqs-4c2c</guid>
      <description>&lt;p&gt;While building the webhook delivery system, my API could only handle around &lt;strong&gt;350 requests per second&lt;/strong&gt;. The architecture looked fine, Redis wasn't the bottleneck and the workers were running normally. After profiling the system, I found the real bottleneck wasn't where I expected, it was the way I was writing events to PostgreSQL. A single architectural change increased throughput to around &lt;strong&gt;1300 req/sec&lt;/strong&gt; while reducing latency by more than 70%.&lt;/p&gt;

&lt;h3&gt;
  
  
  The original design
&lt;/h3&gt;

&lt;p&gt;At the time, the platform already used an asynchronous architecture. Incoming events were accepted by the API, pushed to Redis buffer, and processed by an Ingestion worker in the background.&lt;/p&gt;

&lt;p&gt;The ingestion &lt;strong&gt;worker&lt;/strong&gt; continuously consumed events from Redis and persisted them into PostgreSQL before passing them to the rest of the delivery pipeline.&lt;/p&gt;

&lt;p&gt;The workflow looked like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fddvx3cyijitmpmwwwn76.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fddvx3cyijitmpmwwwn76.png" alt="Single Insert for each event into PostgreSQL" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why it became slow?
&lt;/h3&gt;

&lt;p&gt;For each of the events, the Ingestion worker was inserting an event to PostgreSQL which is fine for a small number of operations. Even though PostgreSQL is fast, when the number of DB operations becomes thousands then this tiny database write operation becomes expensive.&lt;/p&gt;

&lt;p&gt;At first, this doesn't seem like a problem. PostgreSQL is highly optimized and can process thousands of queries per second. However, the issue isn't the &lt;code&gt;INSERT&lt;/code&gt; statement itself, it's everything that happens around it.&lt;/p&gt;

&lt;p&gt;For every event, PostgreSQL has to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Parse and execute the SQL statement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Allocate a new transaction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write changes to the Write-Ahead Log (WAL).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commit the transaction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Send a response back to the application.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now imagine processing &lt;strong&gt;1,000 events&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of writing data once, the database repeats this entire process &lt;strong&gt;1,000 separate times&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Event 1  -&amp;gt; INSERT -&amp;gt; COMMIT
Event 2  -&amp;gt; INSERT -&amp;gt; COMMIT
Event 3  -&amp;gt; INSERT -&amp;gt; COMMIT
...
Event 1000 -&amp;gt; INSERT -&amp;gt; COMMIT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although each operation is relatively inexpensive, the overhead accumulates quickly under sustained traffic. The database spends a significant amount of time managing thousands of small transactions instead of efficiently writing large batches of data.&lt;/p&gt;

&lt;p&gt;As the event rate increased, the Ingestion worker couldn't persist events as quickly as they arrived. The Redis buffer continued to grow, throughput plateaued at around &lt;strong&gt;342 requests per second&lt;/strong&gt;, and overall system latency increased.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The architecture itself wasn't the problem. The bottleneck was the granularity of the database writes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At that point, the next optimization became clear: &lt;strong&gt;reduce the number of database transactions instead of trying to make each transaction faster.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea: Batch Everything
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why was I forcing PostgreSQL to process thousands of small transactions when it could process a few large ones instead?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of writing every event individually, I decided to accumulate multiple events in memory and persist them together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Redis

↓

Pop 100 Events

↓

INSERT
(Event 1)
(Event 2)
(Event 3)
...
(Event 100)

↓

Single COMMIT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this approach, the database performs &lt;strong&gt;one transaction&lt;/strong&gt; instead of one hundred.&lt;/p&gt;

&lt;p&gt;The amount of data being written remains exactly the same, but the transaction overhead is dramatically reduced. Rather than repeatedly opening and committing transactions, PostgreSQL spends more of its time doing what it's optimized for: writing data efficiently.&lt;/p&gt;

&lt;p&gt;To implement this, the Ingestion worker continuously collects events from Redis and flushes them in batches. A batch is written when either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A configured batch size is reached (&lt;strong&gt;100 events&lt;/strong&gt;), or&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A short timeout expires, ensuring that events are not delayed during periods of low traffic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach provides the best of both worlds. During traffic spikes, batches fill quickly, maximizing throughput. During quieter periods, the timeout ensures that events are still persisted promptly without waiting indefinitely for a full batch.&lt;/p&gt;

&lt;p&gt;The architecture itself didn't change, the API still pushes events into Redis, and the Ingestion worker still persists them to PostgreSQL. The only difference was &lt;strong&gt;how&lt;/strong&gt; the worker wrote the data.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Sometimes, the biggest performance improvements don't come from introducing new technologies. They come from using existing ones more efficiently."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The New Architecture
&lt;/h2&gt;

&lt;p&gt;The overall architecture remained exactly the same. The only change was inside the Ingestion worker.&lt;/p&gt;

&lt;p&gt;Instead of processing one event at a time, the worker now consumes multiple events from Redis and persists them to PostgreSQL using a single bulk insert.&lt;/p&gt;

&lt;p&gt;This small implementation change significantly reduced database transaction overhead while keeping the rest of the system unchanged.&lt;/p&gt;

&lt;p&gt;The updated ingestion pipeline now looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F54jg45k14fyqugg3pygj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F54jg45k14fyqugg3pygj.png" alt="Batch insert events to PostgreSQL" width="798" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  One Challenge with Batch Processing
&lt;/h2&gt;

&lt;p&gt;Batching significantly improved throughput, but like most optimizations, it introduced a new trade-off.&lt;/p&gt;

&lt;p&gt;PostgreSQL executes a batch insert as a &lt;strong&gt;single transaction&lt;/strong&gt;. If any row in the batch violates a database constraint for example, a &lt;code&gt;NOT NULL&lt;/code&gt; constraint, a &lt;code&gt;UNIQUE&lt;/code&gt; constraint, or a foreign key constraint, the &lt;strong&gt;entire transaction is rolled back&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That means if a batch contains 100 events and just one of them is invalid, &lt;strong&gt;none of the events are persisted&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Batch of 100 Events
        │
        ▼
INSERT INTO events (...)
        │
        ▼
Event #47 violates a database constraint
        │
        ▼
Entire transaction is rolled back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the trade-off with batching: you gain much higher throughput, but you lose fault isolation within a batch.&lt;/p&gt;

&lt;p&gt;There are several ways a production system can handle this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Validate events before they reach the database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retry failed batches by splitting them into smaller batches to isolate the problematic event.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Move invalid events to a dead-letter queue for later inspection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use features such as &lt;code&gt;ON CONFLICT&lt;/code&gt; where duplicate records are expected.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In HookRelay, this wasn't a major concern because every event had already passed API-level validation before entering the ingestion pipeline. Even so, it's an important consideration whenever batch processing is introduced into a production system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This optimization taught me an important lesson: performance problems aren't always solved by adding new technologies or redesigning an entire system. Sometimes, the biggest improvements come from identifying a single bottleneck and removing it.&lt;/p&gt;

&lt;p&gt;In my case, the architecture was already solid. The problem wasn't Redis, the API, or PostgreSQL itself, it was the cost of performing thousands of tiny database transactions. By simply batching writes, throughput increased from &lt;strong&gt;342 requests/sec&lt;/strong&gt; to &lt;strong&gt;1,259 requests/sec&lt;/strong&gt;, while latency dropped significantly.&lt;/p&gt;

&lt;p&gt;This is just one of several optimizations that went into building HookRelay. In future articles, I'll share other improvements, such as Redis authentication caching, per-tenant queues, circuit breakers, and idempotency, that made the system more scalable and reliable.&lt;/p&gt;

&lt;p&gt;If you're building systems that process high volumes of events, I hope this article helps you avoid the same bottleneck and encourages you to measure first, then optimize where it actually matters.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Designing a Multi-Tenant Webhook Delivery System handling over 1000+ req/sec</title>
      <dc:creator>Abu Bakkar Siddique</dc:creator>
      <pubDate>Sun, 26 Jul 2026 06:45:39 +0000</pubDate>
      <link>https://dev.to/ashraful2502/designing-a-multi-tenant-webhook-delivery-system-handling-over-1000-reqsec-hep</link>
      <guid>https://dev.to/ashraful2502/designing-a-multi-tenant-webhook-delivery-system-handling-over-1000-reqsec-hep</guid>
      <description>&lt;h2&gt;
  
  
  First of all what is a "&lt;strong&gt;webhook&lt;/strong&gt;" and what is a "&lt;strong&gt;webhook delivery&lt;/strong&gt;" system?
&lt;/h2&gt;

&lt;p&gt;So a webhook is a way for one application to notify another application when an event occurs.&lt;/p&gt;

&lt;p&gt;Instead of repeatedly asking, "Has anything changed?", an application can send an HTTP request as soon as something happens. For example, when a customer makes a payment, a payment provider can immediately notify your application that the payment was successful.&lt;/p&gt;

&lt;p&gt;In simple terms, webhooks are event-driven HTTP callbacks that enable systems to communicate in real time.&lt;/p&gt;

&lt;p&gt;A webhook delivery system is the infrastructure responsible for reliably delivering those event notifications to subscriber endpoints.&lt;/p&gt;

&lt;p&gt;Its job goes beyond sending a single HTTP request. A production-grade webhook delivery system must handle retries, failures, rate limiting, monitoring, security, and large volumes of events while ensuring that important notifications reach their destinations.&lt;/p&gt;

&lt;p&gt;Examples of companies that rely heavily on webhook delivery systems include Stripe, GitHub, and Shopify, where millions of webhook events are delivered every day.&lt;/p&gt;

&lt;p&gt;Now that we understand what webhooks are, let's design a webhook delivery system.&lt;/p&gt;

&lt;h2&gt;
  
  
  V1: The Naive Approach
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkqp240vlbvvhwhv0bubt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkqp240vlbvvhwhv0bubt.png" alt="V1: The naive approach" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Naive approach to send webhook events&lt;br&gt;
The first solution most developers think of is straightforward:&lt;/p&gt;

&lt;p&gt;Receive an event.&lt;/p&gt;

&lt;p&gt;Look up the subsc&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;riber's webhook URL.&lt;/li&gt;
&lt;li&gt;Send an HTTP request to that URL.&lt;/li&gt;
&lt;li&gt;Mark the delivery as successful or failed.
This approach works perfectly for small projects and low traffic. If a few webhook events are generated each minute, a single API server can handle everything.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, problems start appearing as traffic grows. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's Wrong With This Design?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A webhook endpoint is outside of our control. It might be slow, unavailable, or return errors.&lt;/p&gt;

&lt;p&gt;If a receiver takes 30 seconds to respond, our application is forced to wait. During traffic spikes, thousands of slow webhook requests can consume server resources and delay other deliveries.&lt;/p&gt;

&lt;p&gt;Even worse, if the server crashes while processing events, some deliveries may be lost entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  V2: Introducing a Queue
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxpdbyt3h7lu7xlj3lj9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxpdbyt3h7lu7xlj3lj9o.png" alt="V2: With queue" width="800" height="398"&gt;&lt;/a&gt;&lt;br&gt;
common improvement is to separate event ingestion from delivery.&lt;/p&gt;

&lt;p&gt;Instead of sending webhooks immediately, the API stores events in a queue. Worker processes consume events from the queue and perform the actual HTTP deliveries.&lt;/p&gt;

&lt;p&gt;This makes the API fast and resilient because receiving events is no longer blocked by slow webhook endpoints.&lt;/p&gt;

&lt;p&gt;New Problems Appear&lt;br&gt;
While queues solve many issues, new challenges emerge:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single failing endpoint can create a growing backlog.&lt;/li&gt;
&lt;li&gt;Continuous retries can waste resources.&lt;/li&gt;
&lt;li&gt;High-volume customers can dominate the queue.&lt;/li&gt;
&lt;li&gt;Rate limits must be respected.&lt;/li&gt;
&lt;li&gt;Temporary outages can trigger retry storms.
As the number of customers grows, ensuring reliable and fair delivery becomes increasingly difficult.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building Toward a Production-Ready System&lt;br&gt;
To address these challenges, modern webhook platforms introduce concepts such as &lt;code&gt;retries with backoff&lt;/code&gt;, &lt;code&gt;dead-letter queues&lt;/code&gt;, &lt;code&gt;rate limiting&lt;/code&gt;, &lt;code&gt;circuit breakers&lt;/code&gt;, &lt;code&gt;delivery tracking&lt;/code&gt;, and &lt;code&gt;tenant isolation&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;These additions improve reliability, but they also increase system complexity.&lt;/p&gt;

&lt;p&gt;The architecture used in HookRelay was designed with these challenges in mind. Rather than treating webhook delivery as a simple HTTP request, it treats delivery as a distributed workflow that must remain reliable under failures, traffic spikes, and multi-tenant workloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  V3: HookRelay Design
&lt;/h2&gt;

&lt;p&gt;The previous architectures are a good starting point, but they begin to break down as traffic increases and more customers start relying on the platform. A production webhook delivery system must do much more than simply send HTTP requests—it needs to ingest events quickly, survive failures, isolate tenants, retry intelligently, and scale without becoming a bottleneck.&lt;/p&gt;

&lt;p&gt;These requirements shaped the design of HookRelay.&lt;/p&gt;

&lt;p&gt;Instead of treating webhook delivery as a single operation, HookRelay breaks it into multiple independent stages. Each stage is responsible for one part of the delivery pipeline and communicates asynchronously with the next. This separation keeps the API responsive, improves reliability, and allows different parts of the system to scale independently.&lt;/p&gt;

&lt;p&gt;At a high level, every event follows this journey:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Producer → API Service → Redis Buffer → Ingest Worker → PostgreSQL → Fanout Worker → Per-Tenant Delivery Queues → Delivery Workers → Consumer Endpoints&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Each stage exists for a specific reason. Some stages improve throughput by batching operations, while others ensure fairness between tenants or increase reliability through retries and circuit breakers. Together, they form a webhook delivery pipeline that can continue operating even when endpoints are slow, temporarily unavailable, or receiving a high volume of traffic.&lt;/p&gt;

&lt;p&gt;Let's walk through the architecture one component at a time and understand why each piece exists. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwyeoo6wmllbb9g21r9e0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwyeoo6wmllbb9g21r9e0.png" alt="V3: HookRelay Architecture" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. API Service
&lt;/h3&gt;

&lt;p&gt;Every webhook event enters the system through the API Service. Its responsibility is not to deliver webhooks directly, but to validate incoming requests and accept events as quickly as possible. The faster the API responds, the more events the system can ingest under heavy load.&lt;/p&gt;

&lt;p&gt;Before an event enters the delivery pipeline, the API performs several important checks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tenant Authentication
&lt;/h3&gt;

&lt;p&gt;Since HookRelay is a multi-tenant platform, every request must belong to a valid tenant. Producers authenticate using an API key, allowing the system to identify which customer owns the event and which delivery rules should be applied.&lt;/p&gt;

&lt;p&gt;To avoid querying PostgreSQL on every request, tenant information is cached in Redis, significantly reducing database load during high traffic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rate Limiting
&lt;/h3&gt;

&lt;p&gt;No single tenant should be able to overwhelm the system. The API enforces per-tenant rate limits before accepting an event.&lt;/p&gt;

&lt;p&gt;HookRelay implements rate limiting using atomic Lua scripts in Redis, ensuring accurate counters even when multiple API instances are running concurrently. Requests that exceed the configured limit receive an HTTP 429 Too Many Requests response.&lt;/p&gt;

&lt;h3&gt;
  
  
  Idempotency
&lt;/h3&gt;

&lt;p&gt;Network failures often cause producers to retry requests. Without protection, the same event could be processed multiple times, resulting in duplicate webhook deliveries.&lt;/p&gt;

&lt;p&gt;To prevent this, every event can include an idempotency key. If the API receives the same key again, it recognizes the request as a duplicate instead of creating another event.&lt;/p&gt;

&lt;h3&gt;
  
  
  Redis Buffer
&lt;/h3&gt;

&lt;p&gt;After passing all validation, the event is not written directly to PostgreSQL. Instead, it is pushed into a Redis buffer, and the API immediately returns 202 Accepted.&lt;/p&gt;

&lt;p&gt;This keeps request latency low because the client doesn't wait for database writes or webhook processing. The actual persistence and delivery pipeline are handled asynchronously by background workers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Not Write Directly to PostgreSQL?
&lt;/h3&gt;

&lt;p&gt;A common question is: Why introduce Redis at all? Why not insert every event directly into PostgreSQL?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The answer is throughput.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If every incoming request performs an individual database insert, PostgreSQL quickly becomes the bottleneck under high traffic. Each request must wait for disk I/O before receiving a response, increasing latency and reducing overall throughput.&lt;/p&gt;

&lt;p&gt;By using Redis as a temporary ingestion buffer, the API only performs a fast in-memory operation before responding. Background workers later drain the buffer and insert hundreds of events into PostgreSQL in batches, dramatically reducing database overhead and allowing the API to remain responsive even during traffic spikes.&lt;/p&gt;

&lt;p&gt;This separation between event ingestion and event persistence is one of the key design decisions that enables HookRelay to scale efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Ingest Worker
&lt;/h2&gt;

&lt;p&gt;At this point, the event has been accepted by the API and stored safely in the Redis buffer. However, Redis is only a temporary staging area, it isn't the system's source of truth.&lt;/p&gt;

&lt;p&gt;The job of the Ingest Worker is to continuously drain events from the Redis buffer, persist them in PostgreSQL, and prepare them for the next stage of the delivery pipeline. By moving these operations into a background worker, the API remains lightweight and can continue accepting new events without waiting for database operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Batch Pop from Redis
&lt;/h3&gt;

&lt;p&gt;Instead of processing one event at a time, the Ingest Worker pulls multiple events from the Redis buffer in a single operation.&lt;/p&gt;

&lt;p&gt;This reduces the number of Redis operations and allows the worker to process large bursts of incoming traffic much more efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Batch Insert into PostgreSQL
&lt;/h3&gt;

&lt;p&gt;Once a batch of events is retrieved, they are inserted into PostgreSQL using a single bulk insert instead of individual database writes.&lt;/p&gt;

&lt;p&gt;PostgreSQL performs significantly better when inserting many rows in one query rather than executing hundreds of separate insert statements. This reduces database overhead, minimizes transaction costs, and improves overall throughput.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bulk Enqueue Fanout Jobs
&lt;/h3&gt;

&lt;p&gt;After the events have been persisted successfully, the Ingest Worker creates fanout jobs in bulk.&lt;/p&gt;

&lt;p&gt;Each fanout job represents the next stage of the pipeline, where the system determines which webhook endpoints should receive the event. Enqueuing these jobs in bulk further reduces Redis overhead and keeps the pipeline efficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Batching?
&lt;/h3&gt;

&lt;p&gt;Batching is one of the biggest performance optimizations in HookRelay.&lt;/p&gt;

&lt;p&gt;Without batching, every incoming event would result in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One Redis read&lt;/li&gt;
&lt;li&gt;One PostgreSQL insert&lt;/li&gt;
&lt;li&gt;One queue operation
At thousands of events per second, these individual operations quickly become expensive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By processing events in batches, the system performs fewer database transactions, fewer queue operations, and fewer network round trips. The result is lower latency, higher throughput, and much better resource utilization.&lt;/p&gt;

&lt;p&gt;This batching strategy was one of the key optimizations that significantly improved HookRelay's ingestion performance while allowing the system to scale under heavy workloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Fanout Worker
&lt;/h2&gt;

&lt;p&gt;Once an event has been safely stored in PostgreSQL, the next question is:&lt;br&gt;
&lt;strong&gt;Who should receive this event?&lt;/strong&gt;&lt;br&gt;
This is the responsibility of the Fanout Worker.&lt;/p&gt;

&lt;p&gt;Rather than sending HTTP requests directly, the Fanout Worker determines which endpoints have subscribed to the event, creates delivery records for each endpoint, and distributes those deliveries across tenant-specific queues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resolve Subscribed Endpoints
&lt;/h3&gt;

&lt;p&gt;Every tenant can register one or more webhook endpoints, and each endpoint can subscribe to different event types.&lt;/p&gt;

&lt;p&gt;When a new event arrives, the Fanout Worker queries the registered endpoints for that tenant and selects only those that are interested in the event being processed.&lt;/p&gt;

&lt;p&gt;For example, if a tenant has three endpoints but only one subscribes to order.created, only that endpoint will receive the event.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create Delivery Records
&lt;/h3&gt;

&lt;p&gt;After identifying the matching endpoints, the Fanout Worker creates a delivery record for each one.&lt;/p&gt;

&lt;p&gt;If an event needs to be delivered to five endpoints, five independent delivery records are created.&lt;/p&gt;

&lt;p&gt;Tracking deliveries separately allows HookRelay to monitor the status of every webhook independently. One endpoint may succeed immediately, another may require retries, while another may eventually end up in the dead letter queue. Each delivery follows its own lifecycle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Per-Tenant Delivery Queues
&lt;/h3&gt;

&lt;p&gt;Instead of placing every delivery into a single shared queue, HookRelay creates a dedicated delivery queue for each tenant.&lt;/p&gt;

&lt;p&gt;This isolates workloads between customers. If one tenant suddenly generates millions of events or has slow webhook endpoints, their deliveries remain confined to their own queue and do not delay deliveries for other tenants.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Is Fanout a Separate Stage?
&lt;/h3&gt;

&lt;p&gt;It might seem tempting to let the Ingest Worker perform endpoint resolution and enqueue delivery jobs immediately. However, separating fanout into its own stage keeps each worker focused on a single responsibility.&lt;/p&gt;

&lt;p&gt;The Ingest Worker is optimized for high-throughput persistence moving events from Redis into PostgreSQL as quickly as possible. The Fanout Worker, on the other hand, performs business logic by resolving subscriptions, creating delivery records, and scheduling deliveries.&lt;/p&gt;

&lt;p&gt;This separation allows each stage to scale independently. If endpoint resolution becomes expensive as the number of tenants grows, additional Fanout Workers can be added without affecting event ingestion. It also keeps the architecture modular, making each stage simpler to reason about, monitor, and optimize.&lt;/p&gt;

&lt;p&gt;At the end of this stage, every delivery has been created and placed into the appropriate tenant queue, ready for the final step: sending the actual webhook requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Delivery Workers
&lt;/h2&gt;

&lt;p&gt;Once the delivery jobs have been distributed into tenant-specific queues, the Delivery Workers take over.&lt;/p&gt;

&lt;p&gt;Their responsibility is straightforward: consume delivery jobs, send HTTP requests to the appropriate webhook endpoints, and record the result of each attempt. Since every tenant has its own queue, multiple Delivery Workers can process deliveries concurrently without one tenant affecting another.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP POST
&lt;/h3&gt;

&lt;p&gt;For every delivery job, the worker constructs an HTTP POST request containing the original event payload and sends it to the registered webhook endpoint.&lt;/p&gt;

&lt;p&gt;A successful 2xx response marks the delivery as successful. Any non-2xx response, network error, or timeout is treated as a failed delivery and handed over to the retry mechanism.&lt;/p&gt;

&lt;h3&gt;
  
  
  HMAC Signing
&lt;/h3&gt;

&lt;p&gt;Webhook payloads should never be trusted blindly. To allow consumers to verify that a request genuinely originated from HookRelay, every outgoing request is signed using HMAC-SHA256.&lt;/p&gt;

&lt;p&gt;The worker includes a signature header generated from the payload and the endpoint's secret. On the receiving side, consumers can generate the same signature and compare the two values to verify the authenticity and integrity of the request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Timeouts
&lt;/h3&gt;

&lt;p&gt;A webhook endpoint is an external service and is completely outside of our control. Some endpoints may respond immediately, while others may become slow or stop responding altogether.&lt;/p&gt;

&lt;p&gt;To prevent workers from waiting indefinitely, every HTTP request is executed with a timeout. If the endpoint fails to respond within the configured time, the attempt is marked as failed and the delivery becomes eligible for retry. This ensures that slow endpoints cannot block workers from processing other deliveries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concurrency
&lt;/h3&gt;

&lt;p&gt;Webhook deliveries are independent of one another, making them ideal for concurrent processing.&lt;/p&gt;

&lt;p&gt;Instead of processing deliveries sequentially, multiple Delivery Workers can execute many HTTP requests in parallel. Combined with tenant-specific queues, this allows HookRelay to achieve high throughput while maintaining fairness between customers. If one tenant experiences slow or failing endpoints, only that tenant's workers are affected, while deliveries for other tenants continue uninterrupted.&lt;/p&gt;

&lt;p&gt;At this stage, the webhook has either been delivered successfully or has failed. In the next section, we'll look at how HookRelay handles failures through retries, exponential backoff, circuit breakers, and dead letter queues.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Reliability Features
&lt;/h2&gt;

&lt;p&gt;In the real world, webhook deliveries rarely succeed 100% of the time. Endpoints can be temporarily unavailable, networks can fail, or servers can become overloaded. A reliable webhook platform must expect these failures and recover from them automatically.&lt;/p&gt;

&lt;p&gt;HookRelay includes several reliability mechanisms to ensure that temporary failures don't result in permanently lost events.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retries
&lt;/h3&gt;

&lt;p&gt;A failed delivery doesn't necessarily mean the webhook should be discarded. Many failures are temporary - a server may be restarting, a network connection may briefly drop, or an application may be experiencing high load.&lt;/p&gt;

&lt;p&gt;Instead of giving up immediately, HookRelay automatically retries failed deliveries. Every failed attempt is recorded, allowing each delivery to progress independently until it either succeeds or reaches the maximum retry limit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exponential Backoff
&lt;/h3&gt;

&lt;p&gt;Retrying immediately after a failure usually makes the situation worse. If a consumer's server is already overloaded, continuously sending new requests only increases the pressure.&lt;/p&gt;

&lt;p&gt;Instead, HookRelay spaces retries using an exponential backoff strategy. The delay between attempts gradually increases from seconds to minutes, and eventually hours giving downstream services time to recover before another delivery attempt is made.&lt;/p&gt;

&lt;h3&gt;
  
  
  Circuit Breaker
&lt;/h3&gt;

&lt;p&gt;Repeatedly sending requests to an endpoint that is clearly unavailable wastes CPU, network bandwidth, and worker capacity.&lt;/p&gt;

&lt;p&gt;To avoid this, HookRelay uses a circuit breaker for every endpoint. After several consecutive failures, the circuit enters the OPEN state, temporarily preventing new requests from being sent to that endpoint. After a cooldown period, a single probe request is allowed. If it succeeds, normal delivery resumes; otherwise, the circuit remains open until the endpoint recovers. This prevents failing endpoints from consuming resources while still allowing automatic recovery.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dead Letter Queue
&lt;/h3&gt;

&lt;p&gt;Not every delivery can be recovered. Some endpoints may remain permanently unavailable or continue returning errors despite multiple retries.&lt;/p&gt;

&lt;p&gt;After the maximum number of delivery attempts has been exhausted, HookRelay marks the delivery as dead instead of retrying forever. Dead deliveries can later be inspected, replayed, or manually retried by an administrator without affecting the rest of the delivery pipeline.&lt;/p&gt;

&lt;p&gt;Together, these reliability mechanisms allow HookRelay to continue delivering webhooks even when downstream services are unreliable, while preventing temporary failures from impacting the overall health of the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Why Per-Tenant Queues?
&lt;/h2&gt;

&lt;p&gt;So far, we've seen how events are ingested, expanded into deliveries, and processed by Delivery Workers. One important design decision remains:&lt;/p&gt;

&lt;p&gt;Why does HookRelay create a separate delivery queue for every tenant instead of using a single shared queue?&lt;/p&gt;

&lt;p&gt;The answer lies in &lt;code&gt;fairness&lt;/code&gt;, &lt;code&gt;isolation&lt;/code&gt;, and &lt;code&gt;scalability&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;The Noisy Neighbor Problem&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Imagine two customers using the platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tenant A generates 50 webhook events per minute.&lt;/li&gt;
&lt;li&gt;Tenant B suddenly generates 100,000 events in a few minutes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If both tenants share the same delivery queue, Tenant B's deliveries will flood the queue, causing Tenant A's webhook deliveries to wait behind thousands of unrelated jobs. Even though Tenant A has very little traffic, their webhooks will experience increased latency simply because another tenant is much busier.&lt;/p&gt;

&lt;p&gt;This is commonly known as the &lt;strong&gt;&lt;em&gt;Noisy Neighbor Problem&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tenant Isolation
&lt;/h3&gt;

&lt;p&gt;HookRelay avoids this problem by creating a dedicated delivery queue for each tenant.&lt;/p&gt;

&lt;p&gt;Every tenant's deliveries are processed independently. If one tenant experiences traffic spikes, slow webhook endpoints, or repeated failures, those issues remain isolated to that tenant's queue. Other tenants continue receiving their webhook deliveries without interruption.&lt;/p&gt;

&lt;p&gt;This isolation makes the platform far more predictable and provides a fairer experience for every customer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Horizontal Scaling
&lt;/h3&gt;

&lt;p&gt;Per-tenant queues also make the system easier to scale.&lt;/p&gt;

&lt;p&gt;As traffic grows, additional Delivery Workers can be added to process more queues concurrently. Since workers consume jobs independently, increasing processing capacity doesn't require changing the overall architecture it simply means running more worker instances.&lt;/p&gt;

&lt;p&gt;This design allows HookRelay to scale horizontally while maintaining tenant isolation and consistent delivery performance.&lt;/p&gt;

&lt;p&gt;By isolating tenants into independent queues, HookRelay ensures that one customer's workload never becomes another customer's problem. This simple architectural decision significantly improves fairness, resilience, and scalability in a multi-tenant webhook delivery platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Performance Optimizations
&lt;/h2&gt;

&lt;p&gt;Building a reliable webhook delivery system isn't enough, it also needs to handle high traffic efficiently. Throughout the development of HookRelay, several optimizations were introduced to reduce latency, minimize database load, and improve overall throughput.&lt;/p&gt;

&lt;h3&gt;
  
  
  Redis Authentication Cache
&lt;/h3&gt;

&lt;p&gt;Every incoming request must be authenticated to identify the tenant and apply the correct delivery rules.&lt;/p&gt;

&lt;p&gt;Performing a PostgreSQL lookup for every request would quickly become expensive under heavy traffic. To avoid this, tenant information is cached in Redis with a short TTL. Most authentication requests are therefore served directly from memory, significantly reducing database load and improving request latency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lua Scripts
&lt;/h3&gt;

&lt;p&gt;Some operations, such as rate limiting and circuit breaker state transitions, must remain atomic even when multiple API or worker instances are running simultaneously.&lt;/p&gt;

&lt;p&gt;Instead of implementing these operations with multiple Redis commands, HookRelay uses Lua scripts that execute atomically on the Redis server. This eliminates race conditions, reduces network round trips, and ensures consistent behavior under concurrent workloads.&lt;/p&gt;

&lt;h3&gt;
  
  
  Batch Inserts
&lt;/h3&gt;

&lt;p&gt;Database writes are one of the most expensive operations in the pipeline.&lt;/p&gt;

&lt;p&gt;Rather than inserting events one at a time, the Ingest Worker collects multiple events from Redis and performs a single bulk insert into PostgreSQL. This significantly reduces transaction overhead, improves database efficiency, and allows the system to process much higher event volumes with the same resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Asynchronous Ingestion
&lt;/h3&gt;

&lt;p&gt;Perhaps the biggest optimization is separating event ingestion from event processing.&lt;/p&gt;

&lt;p&gt;Instead of waiting for database writes, endpoint resolution, and webhook delivery to complete, the API validates the request, pushes the event into the Redis buffer, and immediately returns 202 Accepted. The remaining work is performed asynchronously by background workers.&lt;/p&gt;

&lt;p&gt;This keeps the API responsive even during traffic spikes while allowing each stage of the pipeline to scale independently. These optimizations work together to reduce latency on the critical request path while maximizing throughput in the background. The result is a webhook delivery platform capable of accepting events quickly and processing them efficiently under heavy workloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Performance Results
&lt;/h2&gt;

&lt;p&gt;Designing a scalable architecture is only valuable if it performs well under load. To evaluate HookRelay, I ran a series of load tests using k6, simulating concurrent producers continuously sending events to the POST /events endpoint.&lt;/p&gt;

&lt;p&gt;The goal of these tests wasn't to measure webhook delivery speed, but to measure how efficiently the system could ingest events while keeping API latency low.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load Test Configuration
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Tool: k6
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Duration: 5 minutes&lt;/li&gt;
&lt;li&gt;Concurrent Users: 200 Virtual Users&lt;/li&gt;
&lt;li&gt;Target Endpoint: POST /events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Environment: Docker Desktop running PostgreSQL, Redis, API, and Worker on a single machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  MetricValue
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Throughput &lt;strong&gt;1,259 req/s&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Total Requests &lt;strong&gt;377,843&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;p50&lt;/strong&gt; Latency &lt;strong&gt;73 ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;p95&lt;/strong&gt; Latency &lt;strong&gt;166 ms&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Error rate (&amp;gt;500ms) &lt;strong&gt;0.12%&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;HTTP Failure Rate 0.00%
These results demonstrate that the ingestion pipeline remains responsive even under sustained concurrent traffic. The API consistently returned low response times while successfully accepting every request during the test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optimization Journey&lt;br&gt;
The final numbers weren't achieved in a single iteration. The system evolved through several performance optimizations, including Redis-based authentication caching, Lua-powered rate limiting, asynchronous event ingestion, and batch inserts into PostgreSQL.&lt;/p&gt;

&lt;p&gt;Together, these improvements increased throughput from &lt;strong&gt;&lt;code&gt;342 req/s to 1,259 req/s&lt;/code&gt;&lt;/strong&gt;, while reducing median latency &lt;strong&gt;&lt;code&gt;from 247 ms to 73 ms&lt;/code&gt;&lt;/strong&gt; and decreasing the error rate &lt;strong&gt;&lt;code&gt;from 22.71% to 0.12%&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While there is still room for further optimization, these benchmarks show that the architectural decisions discussed throughout this article particularly asynchronous ingestion, batching, and workload isolation translate into measurable performance improvements under load.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
