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 theid: 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:
Like what you're reading? Try it yourself โ this link supports ChartedTrader at no cost to you.
Try TradingView โ
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 theid 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 a200 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, theid 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 theirchartTimeUtc 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 a200 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.