Receive Webhook Event API
This is the only core api that we are going to focus on.
Endpoint:
POST /api/webhook/events
Request:
{
"event_type": "payment_success",
"event_id": "evt_123456",
"payment_id": "pay_987654",
"amount": 1000,
"currency": "USD",
"status": "success",
"timestamp": "2024-09-15T12:00:00Z",
"signature": "sha256=abcd1234"
}
Other api's which we require are Acknowledge Event API, Fetch Event Logs API, Retry Failed Event API which are pretty much straight forward.
event_id to ensure that multiple deliveries of the same event are not processed more than once.event_id should not lead to inconsistent state changes.
Great! Let's proceed to the Database Design for the Webhook Notification Service. We will define the data model, including key entities and their relationships, and draw an Entity-Relationship (ER) diagram using Mermaid.
The database design for the Webhook Notification Service will focus on capturing and storing event data, ensuring idempotency, and supporting logging for audit and retry mechanisms.
The event table will store information about each webhook event received.
| ColumnTypeDescription | ||
event_id | VARCHAR | Primary key, unique identifier for the event (UUID format). |
event_type | VARCHAR | Type of event (e.g., payment_success, payment_failure). |
payment_id | VARCHAR | Identifier for the related payment transaction. |
amount | DECIMAL | Amount involved in the transaction. |
currency | VARCHAR | Currency code (e.g., USD). |
status | VARCHAR | Event status (e.g., success, failure, pending). |
signature | VARCHAR | Cryptographic signature for validation. |
created_at | TIMESTAMP | Timestamp when the event was received. |
updated_at | TIMESTAMP | Timestamp when the event status was last updated. |
The event_log table will store detailed logs for each event, providing a historical record of actions taken.
| ColumnTypeDescription | ||
log_id | BIGINT | Primary key, auto-incremented log entry ID. |
event_id | VARCHAR | Foreign key referencing the event table. |
status | VARCHAR | The status at the time of logging (e.g., success, failure). |
message | TEXT | Detailed log message (e.g., error description or action). |
logged_at | TIMESTAMP | Timestamp when the log entry was created. |
The retry_log table will track retries for events that failed to process on the first attempt.
| ColumnTypeDescription | ||
retry_id | BIGINT | Primary key, auto-incremented log entry ID. |
event_id | VARCHAR | Foreign key referencing the event table. |
retry_count | INT | Number of retry attempts. |
retry_status | VARCHAR | The outcome of the retry attempt (e.g., success, failure). |
retry_at | TIMESTAMP | Timestamp when the retry attempt was made. |
Here’s a Mermaid diagram representing the relationship between the entities (Event, Event Log, Retry Log):
event_id field in the event, event_log, and retry_log tables should be indexed to ensure fast lookup times.status field in the event table would help in retrieving events based on their status (e.g., pending, success, failed).event_id in the event_log and retry_log tables should be a foreign key that references the event table to maintain referential integrity.event_type or event_id to distribute data across multiple database nodes.The Webhook Notification Service consists of several core components that work together to receive, validate, process, and store webhook events. Here's a breakdown of the components:
The Event Validator ensures that each webhook event is authentic and properly formatted before further processing. This is crucial for security and preventing malicious data from entering the system.
event_id, payment_id, status, etc.) and ensures they adhere to expected formats.400 Bad Request response.The Retry Mechanism ensures that events that fail during processing due to transient errors (e.g., database downtime or network issues) are retried without manual intervention.
Implementing idempotency ensures that duplicate events are processed only once, but it introduces additional storage and processing overhead to track each event_id. Each event must be uniquely identifiable and stored with its status, which can increase the load on the database.
A lighter solution could be to discard duplicate events at the network level, but this sacrifices reliability if duplicate events are legitimate and need to be handled.
Using exponential backoff for retries reduces the risk of overwhelming the system with retries during a failure. However, this can delay the resolution of issues, as events might take longer to be retried, especially during high traffic periods.
A constant retry interval would lead to faster processing of retries but could overload the system if failures persist.
event_type or payment_id to distribute load more effectively across multiple processing nodes or database partitions.