Possibility to send a high number of emails without keeping own server for email delivery.
We've implemented hooks delivery system with Amazon Simple Notification Service (SNS) and proxy server that process subscribe and redirect requests. Little coding was required and responsibility of webhook delivery is assigned to external service.
To achieve project objectives we’ve consider several implementation options:
We have the following components that are responsible for events in our system:
The simple way to inform 3rd party API it’s just to make HTTP request to the hook URL directly from consumer, as displayed on the following diagram:
Accordingly, we came to the conclusion that this approach will not give us expected results or satisfy needs in a full manner.
Therefore we’ve started to consider other options.
We use a lot of AWS services at that moment and already have a bunch of SQS Messaging Queues. Main idea for the solution it is to use seperate queue for hooks (webhooks) and consumer to process this Queue. Take a look at the schema that shows how SQS Queue works:
In this manner our main app flow does not depend on working state of external APP and we are able to implement retries via SQS Queue.
The flow of retry is like so/as follows:
The flow is displayed on diagram below:
This option was a way better, however, not all of our primary goals were about to be met by doing implementation via SQS Queue.
Another way to implement webhooks delivery is using AWS SNS. The service developed for delivering notifications and can send them via HTTP, the same way as webhooks do. Also if notification delivery is failed, SNS is responsible for retry delivery and we can use linear or logarithmic function to manage retry frequency.
This solution will give us desirable outcome, however it can not be applied due to these 2 reasons:
The SNS was designed for communication between different components within one system and not for communication among different components of different systems with different owners. Hence, we need a proxy component inside our system that SNS can communicate with.
Let's take a look at the scheme of proposed webhooks implementation using SNS:
Flow of hooks delivery using SNS:
Schema of proxy API is shown below:
After considering each implementation option in terms of benefit it will bring and required resources for its execution, we’ve chosen to go with the webhooks delivery by SNS Notification. With SNS and simple proxy server we’ve implemented hooks delivery system with minimum coding involved and shifted responsibility of webhook delivery to external service. As a result, we are able to send about 20 000 events per minute without any scaling, which is even higher compare to planned 10 000 events/min. The major bottleneck is the proxy, but we designed this one for scaling so throughput can be easily increased.
We wrote our proxy using Node.js platform. The proxy hosted on EC2 t2.small instance and can process about 4000 concurrent requests with throughput about 400 req/sec. The proxy doesn’t have any interaction with the database since all data for redirect passed in URL. This gives us an option to do a horizontal scaling. If we place our proxy behind load balancer, then we will be able to add more server instances and as a result obtain 2 times higher throughput.
Vertical scaling won’t give us the same effect. When we scale node processes within one server instance we can get about 30% higher throughput for each additional processor kernel. Therefore horizontal scaling is more suitable and effective approach.
We don’t need to worry about scaling SNS because AWS does it automatically, we only have to send proper count of messages.