Webhook received, but not persisted
This error occurs when the endpoint receives the webhook, but the event is not saved before processing starts.
Unlike the timeout error, the request may have been accepted normally. The problem arises when processing fails and there is no record available for lookup, auditing, or reprocessing.
How to identify
- there is no record of the received payload;
- only successfully processed events appear in the history;
- there is no status for received or failed events;
- the system cannot confirm whether the webhook arrived;
- failed events cannot be reprocessed;
- there are status mismatches without enough information for diagnosis.
How to fix
- Create a table, queue, or structure to store the events.
- Record the payload or the data required for reprocessing.
- Save the event type, the time, and the related identifiers.
- Record the event before running the business logic.
- Define internal statuses, such as received, processed, and error.
- Send the event for processing only after it has been persisted.
- Keep failed events available for lookup.
- Implement a safe reprocessing mechanism.
Recommended flow: receive → validate → persist → respond → process.
Diagnostic flow
1. Persisting the receipt
%%{init: {"flowchart": {"nodeSpacing": 18,"rankSpacing": 24,"diagramPadding": 4,"padding": 7
}}}%%
flowchart TD
A["Webhook received by the endpoint"] --> B{"Is there a record of the event?"}
B --> BSim(("Yes"))
B --> BNao(("No"))
BNao --> C["Find where the event should be stored"]
C --> D["Create an event table, queue, or store"]
D --> H["Save payload, type, time, and identifiers"]
BSim --> E{"Was it recorded before processing?"}
E --> ESim(("Yes"))
E --> ENao(("No"))
E --> EDuvida(("Not sure"))
ENao --> F["Change the order of the flow"]
EDuvida --> G["Check code, logs, and transactions"]
G --> F
F --> H
ESim --> I{"Is there an internal event status?"}
I --> ISim(("Yes"))
I --> INao(("No"))
INao --> H
ISim --> J["Release the event for processing"]
H --> J
classDef inicio fill:#DBEAFE,stroke:#2563EB,color:#1E3A8A,stroke-width:3px
classDef decisao fill:#FEF3C7,stroke:#D97706,color:#78350F,stroke-width:3px
classDef correcao fill:#FFEDD5,stroke:#EA580C,color:#7C2D12,stroke-width:2px
classDef validacao fill:#E0F2FE,stroke:#0284C7,color:#0C4A6E,stroke-width:2px
classDef sucesso fill:#DCFCE7,stroke:#16A34A,color:#14532D,stroke-width:3px
classDef analise fill:#FEE2E2,stroke:#DC2626,color:#7F1D1D,stroke-width:3px
classDef respostaSim fill:#22C55E,stroke:#15803D,color:#FFFFFF,stroke-width:3px
classDef respostaNao fill:#EF4444,stroke:#B91C1C,color:#FFFFFF,stroke-width:3px
classDef respostaDuvida fill:#8B5CF6,stroke:#6D28D9,color:#FFFFFF,stroke-width:3px
class A inicio
class B,E,I decisao
class D,F,H correcao
class G validacao
class J sucesso
class C analise
class BSim,ESim,ISim respostaSim
class BNao,ENao,INao respostaNao
class EDuvida respostaDuvida
linkStyle default stroke:#94A3B8,stroke-width:2px
linkStyle 1,7,15 stroke:#22C55E,stroke-width:4px
linkStyle 2,8,16 stroke:#EF4444,stroke-width:4px
linkStyle 9 stroke:#8B5CF6,stroke-width:4px
2. Failure and reprocessing
%%{init: {"flowchart": {"nodeSpacing": 18,"rankSpacing": 24,"diagramPadding": 4,"padding": 7
}}}%%
flowchart TD
A["Event persisted and available for processing"] --> B{"Did processing finish successfully?"}
B --> BSim(("Yes"))
B --> BNao(("No"))
BSim --> C["Update the status to processed"]
BNao --> D["Record the error status"]
D --> E{"Can the event be reprocessed?"}
E --> ESim(("Yes"))
E --> ENao(("No"))
E --> EDuvida(("Not sure"))
ESim --> F["Fix the cause and reprocess"]
EDuvida --> G["Validate payload, history, and identifiers"]
G --> F
ENao --> H["Implement safe reprocessing"]
H --> F
F --> I{"Did reprocessing work?"}
I --> ISim(("Yes"))
I --> INao(("No"))
ISim --> C
INao --> J["Check the current state in the API"]
J --> K["Reconcile the mismatch"]
C --> L["Maintain history and monitoring"]
K --> L
classDef inicio fill:#DBEAFE,stroke:#2563EB,color:#1E3A8A,stroke-width:3px
classDef decisao fill:#FEF3C7,stroke:#D97706,color:#78350F,stroke-width:3px
classDef correcao fill:#FFEDD5,stroke:#EA580C,color:#7C2D12,stroke-width:2px
classDef validacao fill:#E0F2FE,stroke:#0284C7,color:#0C4A6E,stroke-width:2px
classDef sucesso fill:#DCFCE7,stroke:#16A34A,color:#14532D,stroke-width:3px
classDef analise fill:#FEE2E2,stroke:#DC2626,color:#7F1D1D,stroke-width:3px
classDef respostaSim fill:#22C55E,stroke:#15803D,color:#FFFFFF,stroke-width:3px
classDef respostaNao fill:#EF4444,stroke:#B91C1C,color:#FFFFFF,stroke-width:3px
classDef respostaDuvida fill:#8B5CF6,stroke:#6D28D9,color:#FFFFFF,stroke-width:3px
class A inicio
class B,E,I decisao
class D,F,H,K correcao
class C,J validacao
class L sucesso
class G analise
class BSim,ESim,ISim respostaSim
class BNao,ENao,INao respostaNao
class EDuvida respostaDuvida
linkStyle default stroke:#94A3B8,stroke-width:2px
linkStyle 1,6,15 stroke:#22C55E,stroke-width:4px
linkStyle 2,7,16 stroke:#EF4444,stroke-width:4px
linkStyle 8 stroke:#8B5CF6,stroke-width:4px
How to prevent
Make persistence a mandatory step before processing. Maintain internal statuses, event history, and mechanisms for reprocessing, duplicate handling, and reconciliation.
Receiving the webhook is not enough. The event must be recorded before it is processed.
Updated 2 days ago
Did this page help you?
