Webhook evidence checklist

Engineering note · Webhook reliability

A Webhook Bridge Is Not Reliable Until Duplicate Alerts Are Harmless

Stop TradingView webhook duplicate orders with a persisted alert ID, explicit broker outcomes and restart-safe reconciliation. Includes three acceptance tests.

9 minute read

Symptom

One TradingView alert creates two broker orders after a retry or reconnect.

Root boundary

The receiver crosses the broker side-effect boundary without a persisted outcome.

Hard rule

One stable alert ID may resolve to no more than one broker ticket.

The happy path is not the reliability test

A bridge can receive a TradingView webhook, translate the payload and place an MT4 or MT5 order in a clean demo run. That proves the basic path works. It does not prove the bridge is safe when the network repeats a request, the broker response disappears or the process restarts at the worst moment.

This note comes from a public discussion about testing a TradingView to MT4 bridge. The useful question was not whether one market order could get through. It was whether duplicate delivery, broker rejection and restart recovery had explicit outcomes. The proposed acceptance rule was simple: the same alert ID may arrive twice, but the bridge may create only one broker ticket.

The sequence that must survive a retry

Idempotency means repeated handling of one logical event has the same external effect as handling it once. It does not mean ignoring all similar alerts. The identity has to describe one specific trading decision, such as strategy, symbol, side, bar time and a source sequence. A database uniqueness rule then owns that identity.

TradingView

alert_id: A-1042

Persisted receiver

RECEIVED → SUBMITTING

Broker boundary

one client order key

A second request for A-1042 does not start this sequence again. It reads the existing row and returns the stored result. If that row is SUBMITTING or UNCERTAIN, the bridge reconciles first. It does not guess that the first attempt failed.

Use an explicit state model

A boolean such as processed is too weak. It cannot tell you whether validation failed, an order was accepted or a response was lost. Store each transition and the non-secret evidence needed to explain it.

StateWhat is knownAllowed next action
RECEIVEDThe raw request and stable alert ID are stored.Safe to validate. A duplicate can return the stored state.
VALIDATEDSchema, symbol, side and quantity passed the frozen rules.Safe to prepare one broker request.
SUBMITTINGA broker request may be in flight.Do not submit again until the broker state is reconciled.
ACCEPTEDThe broker returned a confirmed ticket or order ID.Return the same recorded success for every duplicate.
REJECTEDThe broker rejected the request with a terminal reason.Return the recorded rejection. Never retry blindly.
UNCERTAINThe request timed out or the connection broke during submission.Query by client order key, then resolve to accepted or rejected.

The smallest reliable repair

  1. 1

    Create a stable event identity.

    Prefer a source-provided ID. If none exists, derive one from frozen fields that identify one logical decision.

  2. 2

    Persist before the side effect.

    Insert the raw request and RECEIVED state under a unique alert ID before acknowledging success or contacting the broker.

  3. 3

    Carry one client order key.

    Use the alert identity in the broker request or in the bridge ownership metadata when the API permits it.

  4. 4

    Record every outcome.

    Keep timestamps, transition reason, broker code and ticket reference. Redact credentials and account secrets.

  5. 5

    Reconcile before any retry.

    For an uncertain request, query broker history or bridge-owned orders by the client key before deciding that a new submission is safe.

Three acceptance tests

These cases make the reliability claim pass or fail. Run them on demo or in a controlled no-transaction fixture. A single clean order is not enough evidence.

Test 1

Duplicate delivery

Input: The exact same alert ID arrives twice.

Pass: There is exactly one broker ticket. Both HTTP calls resolve to the same stored outcome.

Test 2

Restart recovery

Input: The bridge restarts while one alert is SUBMITTING.

Pass: It reloads the stored alert, reconciles the broker state and finishes or rejects it exactly once.

Test 3

Rejection or timeout

Input: The broker rejects the request or the response times out.

Pass: The alert reaches an auditable terminal or reconciliation state. No blind resubmit occurs.

What this does not prove

Some broker APIs have a true idempotency field. Others only expose a comment, magic number, label or client order ID. When no atomic broker-side key exists, the receiver can still reduce risk with persisted ownership and reconciliation, but there remains a narrow failure window that must be documented and tested.

This model also does not prove that the TradingView signal was correct. Alert snapshots, intrabar calculation, higher-timeframe data, symbol mapping, volume conversion and broker execution rules are separate boundaries. Freeze and test them separately. And none of these software checks prove profitability or future trading results.

Free next step

Trace one alert before changing the bridge

Use the free mismatch checklist to collect one TradingView event, its webhook receipts and the broker outcome on one time basis. If the divergence is still unclear, the sample report shows the exact evidence format used for a bounded diagnostic.

For a real incident, the bounded Pine webhook reconciliation service works from authorized source, redacted payloads and logs. Live-account access is not required.