Estimate the scale of the system. Consider daily active users, read/write ratio, storage requirements, bandwidth, and any relevant QPS calculations...
Define the APIs expected from the system. This is your chance to analyze and define the read and write paths so that you can come up with the high-level design...
GET /api/v1/getWebhooks
GET /api/v1/getWebhook/{id}
GET /api/v1/getStatus
POST /api/v1/createWebhook
POST /api/v1/updateWebhook
GET /api/v1/metrics
POST /api/v1/webhook/events
POST /api/v1/acknowledgement
DELETE /api/v1/deleteWebhook/{id}
API Gateway: To route traffic based on the endpoint getting hit. Used for authentication and for rate limiting the requests.
Load Balancer: To balance the load received so that high availability and reliability is achieved.
Kafka: It is used as a high throughput queue to store the requests that are received. With this even if there is a down time it is easy to recover as kafka will have the missed requests. User will receive 200 OK immediately in case of failure the request is enqueued safely.
Webhook Service: Will have the get, create, update, delete and get events apis.
Metrics: Will record all the metrics both in terms of traffic and for infrastructure.
Acknowledgement: Sends out acknowledgement based on the output received from the webhook apis.
Postgres - persistent storage to have all the data of the invocations, statuses and events that are taking place. Every invocation will have idempotency key to avoid redundant runs. We will be sharding the DB to avoid hot keys.
EventProcessor: routes events to type-specific handlers.
Redis: To cache the requests and take care of concurrent redundant requests and reduce load on the db and response time.
DeadLetter Queue: when a event fails after all the retries it will be sent to DLQ for the team to review and rectify the error.
Webhook:
Id, name, status, createdAt, TriggeredAt, subsriber_url, event_type, secret_key
Events:
id, type, webhook_id, status, createdAt, updatedAt, payment_id, amount, signature, payload,
EventDeliveries:
id, event_id, webhook_id, status, retry_count, http_status_code, next_retry_at, last_attemp_at, created_at, updated_at
Kafka: It is used as a high throughput queue to store the requests that are received. With this even if there is a down time it is easy to recover as kafka will have the missed requests. User will receive 200 OK immediately in case of failure the request is enqueued safely.
Why go with this instead of just a standard message queue. Using this we can have a graceful degradation since it can enqueue requests unlike message queue which cannot.
Postgres: persistent storage to have all the data of the invocations, statuses and events that are taking place. Every invocation will have idempotency key to avoid redundant runs. We will be sharding the DB to avoid hot keys.