๐Ÿ“– Guides

Fix TradingView Webhook Duplicates & Out-of-Order (2026)

โš ๏ธ Disclosure: Some links on this page are affiliate links. If you sign up through them, I may earn a commission โ€” at no extra cost to you. I only review tools I actually use.
# Fix TradingView Webhook Duplicates & Out-of-Order (2026)

If you've ever set up a TradingView webhook to automate your trading or log alerts to a database, you've probably run into a frustrating problem: duplicate alerts. You get three identical signals for a single crossover, or your alerts arrive in the wrong order, causing your bot to execute trades out of sequence.

This isn't a bug in TradingViewโ€”it's a feature of how webhooks handle network latency and server downtime. TradingView uses a retry queue to ensure your alerts aren't lost if your server is temporarily unreachable. But without proper handling, that retry queue becomes your biggest enemy.

In this guide, we'll break down exactly how TradingView's webhook retry system works, why out-of-order delivery happens, and how to implement idempotency keys and timestamp filtering to ensure your automation pipeline is bulletproof.

> About this guide: I'm Lawrence, the writer behind supa.is. Between February and May 2026 I've published 150+ articles on supa.is across crypto and brokerage tooling โ€” including 20+ TradingView-specific guides (recent examples: TradingView Webhook to Telegram Bot, TradingView Alert Not Triggering? 12 Fixes, TradingView Alert: Once Per Bar vs Once Per Bar Close). The most-repeated reader question across that TradingView archive is exactly how to handle duplicate webhook payloads and out-of-order delivery, which is why I'm publishing this standardized guide instead of answering one-off.

> Disclosure: This article contains affiliate links. We may earn a commission at no extra cost to you if you sign up for TradingView through our links.

How TradingView Webhooks Actually Work

Before we can fix duplicate alerts, we need to understand the mechanics of the TradingView webhook delivery system. When an alert condition is met on your chart, TradingView generates a JSON payload and sends an HTTP POST request to the URL you specified in your alert settings.

The structure of this payload is standardized. It includes the alert ID, the alert message, the time the alert was triggered, and the payload you defined in the alert settings.

{
  "id": "123456",
  "alertId": "789012",
  "alertName": "EMA Crossover Long",
  "time": "2026-06-24T10:00:00.000Z",
  "timeUtc": "2026-06-24T10:00:00.000Z",
  "exchange": "BINANCE",
  "symbol": "BTCUSDT",
  "interval": "5",
  "chartTime": "2026-06-24T10:00:00.000Z",
  "chartTimeUtc": "2026-06-24T10:00:00.000Z",
  "isSynchronization": false,
  "payload": {
    "action": "BUY"
  }
}

*(Note: The exact fields may vary slightly depending on the TradingView API version, but the core elements remain the same.)*

The Retry Queue Mechanism

Here is where the trouble starts. TradingView expects your receiving server to respond with a 2xx status code (like 200 OK) to acknowledge receipt of the alert.

If your server is down for maintenance, if your API rate limit is hit, or if there's a network timeout, TradingView does not just give up. It puts the alert into a retry queue and attempts to resend it.

According to TradingView's official documentation on webhook resubmission, the retry queue will attempt to resend the payload a maximum of 3 times if the initial request fails. The delays between these retries are typically 1 minute, 5 minutes, and 15 minutes after the initial failure (as of June 2026, TradingView Webhook Resubmission Docs). If your server eventually comes back online and responds with a 200 OK to the *second* attempt, the alert is marked as delivered.

However, here is the catch: if your server was down for 5 minutes, and TradingView sent the alert 3 times during that window, your server will receive 3 identical payloads when it comes back online. If your code doesn't know how to handle this, it will process the same signal three times, resulting in three duplicate trades or three duplicate log entries.

Why Out-of-Order Delivery Happens

Out-of-order delivery is a different beast. It occurs when you have multiple alerts set up on different timeframes or symbols, and they trigger simultaneously.

For example, you have a 5-minute EMA crossover alert on BTCUSDT and a 15-minute RSI alert on ETHUSDT. Both trigger at the exact same second. TradingView queues them up and sends them to your webhook.

Because of network routing, latency, or your server's processing speed, the 15-minute ETHUSDT alert might arrive *after* the 5-minute BTCUSDT alert, even if you intended to process them sequentially. If your trading logic relies on a strict chronological order of events, out-of-order delivery can cause your bot to make the wrong decision.

The Solution: Idempotency Keys

The industry-standard solution for duplicate webhook payloads is idempotency. In computer science, an idempotent operation is one that can be applied multiple times without changing the result beyond the initial application.

In the context of TradingView webhooks, this means your server needs to recognize that it has already seen and processed a specific alert, and ignore subsequent duplicates.

How to Implement Idempotency

Every TradingView webhook payload contains a unique id field. This is your idempotency key.

Here is how you should structure your webhook receiver:

1. Receive the payload: Your server gets the JSON from TradingView.

2. Extract the id: Pull the id field from the JSON. 3. Check your database: Query your local database (or an in-memory store like Redis) to see if this id already exists. 4. If it exists: Log the duplicate, send a 200 OK response to TradingView (to clear the retry queue), and do not process the alert. 5. If it doesn't exist: Insert the id into your database, process the alert, and send a 200 OK response.

Let's look at a conceptual Node.js example:

๐Ÿ’ก TradingView

Like what you're reading? Try it yourself โ€” this link supports ChartedTrader at no cost to you.

Try TradingView โ†’
๐ŸŽ You receive: 30-day free trial (Essential / Plus / Premium) ยท no credit card needed

app.post('/webhook', async (req, res) => {
  const payload = req.body;
  const alertId = payload.id; // The idempotency key

  // Check if we've already processed this alert
  const existingAlert = await db.alerts.find({ id: alertId });

  if (existingAlert) {
    console.log(`Duplicate alert received: ${alertId}`);
    return res.status(200).send('OK'); // Acknowledge to clear TradingView retry queue
  }

  // Process the alert
  await processAlert(payload);

  // Store the idempotency key
  await db.alerts.insert({ id: alertId, processedAt: new Date() });

  res.status(200).send('OK');
});

By implementing this, you ensure that even if TradingView retries the same alert 3 times due to a network blip, your server will only execute the trade or log the entry once.

Fixing Out-of-Order Alerts with Timestamps

Idempotency solves the duplicate problem, but it doesn't solve the out-of-order problem. If Alert A triggers at 10:00:00 and Alert B triggers at 10:00:01, but Alert B arrives at your server first, your logic might execute B before A.

To fix this, you need to rely on the time or chartTimeUtc fields in the TradingView payload, not the arrival time at your server.

The Timestamp Buffer Approach

If your trading logic requires strict chronological processing, you should implement a timestamp buffer.

Instead of processing alerts the moment they arrive, hold them in a queue for a short period (e.g., 5-10 seconds). During this buffer window, collect all incoming alerts. Once the buffer expires, sort the alerts by their chartTimeUtc timestamp, and then process them in chronological order.

// Conceptual logic
const buffer = [];

app.post('/webhook', (req, res) => {
  buffer.push(req.body);
  res.status(200).send('OK');
});

// Every 10 seconds, process the buffer
setInterval(async () => {
  if (buffer.length > 0) {
    // Sort by the time the alert was triggered on TradingView
    buffer.sort((a, b) => new Date(a.chartTimeUtc) - new Date(b.chartTimeUtc));
    
    for (const alert of buffer) {
      await processAlert(alert);
    }
    buffer.length = 0; // Clear the buffer
  }
}, 10000);

This approach ensures that even if network latency causes Alert B to arrive before Alert A, your system will recognize that Alert A was triggered first and process it accordingly.

Other Common Webhook Pitfalls

Beyond duplicates and out-of-order delivery, there are a few other common issues that trip up traders when setting up TradingView webhooks.

1. The "Once Per Bar" vs "Once Per Bar Close" Problem

If you are getting duplicate alerts that aren't caused by the retry queue, the issue might be your alert settings. TradingView offers two modes for alert triggering:

* Once Per Bar: The alert triggers as soon as the condition is met *during* the formation of the current candle. If the price dips and triggers the condition, then bounces back and triggers it again within the same candle, you will get multiple alerts.

* Once Per Bar Close: The alert only triggers once the current candle closes and the condition is confirmed.

For most automated trading setups, Once Per Bar Close is the safer option. It prevents false signals caused by wicks and mid-candle volatility. If you've been getting duplicate alerts despite having idempotency keys, switch your alerts to "Once Per Bar Close." (For a deep dive on this, check out our guide on Once Per Bar vs Once Per Bar Close).

2. Webhook Timeout Errors

If your server takes too long to process an alert, TradingView will assume the request failed and add it to the retry queue. The default timeout for TradingView webhooks is relatively short.

If you are doing heavy computation (like running a complex strategy test or fetching data from multiple APIs) before responding to TradingView, you will hit this timeout. The solution is to respond immediately and process the alert asynchronously.

app.post('/webhook', (req, res) => {
  // Respond immediately to clear the retry queue
  res.status(200).send('OK');
  
  // Process the alert in the background
  processAlertAsync(req.body);
});

3. Alert Not Triggering at All

If your webhooks aren't firing even when conditions are met, it's usually due to one of two things:

1. The alert is set to a timeframe you don't have open on your chart. 2. The alert is muted or paused.

Before building complex retry logic, make sure your alerts are actually firing. We have a comprehensive checklist for this in our TradingView Alert Not Triggering? 12 Fixes guide.

Building a Reliable Webhook Pipeline: A Checklist

If you are setting up a new TradingView webhook automation pipeline, use this checklist to ensure you don't fall into the duplicate/out-of-order traps:

1. Set alerts to "Once Per Bar Close": Unless you specifically need real-time mid-candle signals, this prevents phantom duplicates.

2. Implement Idempotency: Store the id field from the TradingView payload in a database. Reject any payload with an existing id. 3. Respond with 200 OK immediately: Don't make TradingView wait for your server to process the trade. Acknowledge receipt, then process in the background. 4. Use a Timestamp Buffer: If chronological order matters, hold alerts for 5-10 seconds, sort by chartTimeUtc, and then process. 5. Monitor your retry queue: Log any duplicates that hit your idempotency filter. If you are seeing a high volume of duplicates, your server might be timing out or going down frequently.

FAQ

Why does TradingView retry webhooks?

TradingView retries webhooks to ensure that your alerts aren't lost if your server is temporarily unreachable. If your server doesn't respond with a 200 OK status code, TradingView assumes the delivery failed and puts the alert in a retry queue, attempting to resend it up to 3 times with delays of 1, 5, and 15 minutes (as of June 2026, source).

What is an idempotency key in TradingView webhooks?

An idempotency key is a unique identifier used to prevent duplicate processing. In TradingView webhooks, the id field in the JSON payload serves as the idempotency key. By storing this id in your database, you can check if an alert has already been processed and ignore subsequent duplicate attempts from the retry queue.

How do I fix out-of-order alert delivery?

To fix out-of-order delivery, implement a timestamp buffer. Instead of processing alerts immediately upon arrival, hold them in a queue for a few seconds. Once the buffer expires, sort the alerts by their chartTimeUtc timestamp and process them in chronological order.

Should I use "Once Per Bar" or "Once Per Bar Close" for webhooks?

For most automated trading setups, "Once Per Bar Close" is recommended. "Once Per Bar" can trigger multiple times within a single candle if the price fluctuates, leading to duplicate alerts. "Once Per Bar Close" waits for the candle to close before triggering, ensuring the signal is confirmed.

My webhook is timing out and causing duplicates. What should I do?

If your webhook is timing out, it means your server is taking too long to respond to TradingView. You should respond with a 200 OK status code immediately upon receiving the payload, and then process the alert asynchronously in the background. This clears the retry queue while allowing your server time to complete heavy computations.

Risk Warning

> Risk Warning: Crypto trading involves substantial risk of loss. Never invest more than you can afford to lose. This is not financial advice.

๐Ÿงฎ Free TradingView calculator

Strategy Expectancy โ†’
TP / SL / win-rate / Kelly criterion math โ€” no fake backtest required
TradingView

Ready to get started? Use the link below โ€” it helps support ChartedTrader at no cost to you.

Try TradingView โ†’
๐ŸŽ You receive: 30-day free trial (Essential / Plus / Premium) ยท no credit card needed
๐Ÿ“ˆ

About the author

I'm a systematic trader running live strategies on IB (USDJPY momentum) and Hyperliquid (crypto perps). Every tool reviewed here is something I've used with real capital. Questions? Reach out.

๐Ÿ“š Related Articles

๐Ÿ“–
Guides

How to Trade Crypto for Beginners on OKX: Step-by-Step

A step-by-step guide to trading crypto on OKX for beginners. Learn how to set up your account, place spot trades, understand fees, and manage risk safely.

June 21, 2026 โฑ 11 min read
๐Ÿ“–
Guides

Fix TradingView to IBKR Integration Errors (2026)

TradingView to IBKR webhook timeouts, API permission denied, and bad price errors? Here are the exact fixes for 2026 integration failures.

June 20, 2026 โฑ 10 min read
๐Ÿ“–
Guides

Hyperliquid Points Season 3: How to Earn the Airdrop (2026)

Hyperliquid Points Season 3 is live. Learn how the scoring algorithm works, which assets yield the highest points, and how to structure trades to maximize efficiency without blowing up your account.

June 19, 2026 โฑ 12 min read

๐Ÿ“ฌ Get weekly trading insights

Real trades, honest reviews, no fluff. One email per week.