Link Tracking is a core activity for Marketing and CRM SaaS companies. Link Tracking often an early system bottleneck, one that creates a lousy user experience and frustrates your clients. In this article I’m going to show a common synchronous design, discuss why it fails to scale, and show how to overcome scaling issues by making the design asynchronous.
What Is Link Tracking?
Link Tracking allows you to track who clicks on a link. This lets you measure the effectiveness of your marketing, learn what offers appeal to which clients, and generally track user engagement. When you see a link starting with fb.me or lnkd.in, those are tracking links for Facebook and LinkedIn.
Instead of having a link go to original target, the link is changed to a tracking link. The system will track 3 pieces of data: which client, which user, and what url, and then redirect the user’s browser to the original link.
A Simple Synchronous Design
Here’s what that looks like as a sequence diagram.
There are 2 trips to the database, first to discover what the original link is, and a second to record the click. After all of that is done, the original link is returned to the user and their browser is redirected to the actual content they are looking for.
Best case on a cloud host like AWS the Server + Database time will be about 10ms. That time will be dwarfed by the 50-100ms from general network latency getting to AWS, through the ELB and to the server.
This design is simple, speedy, and works well enough for your early days.
Why Synchronous Processing Fails to Scale
Link Tracking events tend to be spikey – there’s an email blast, an article is published, or some tweet goes viral. Instead of 150,000 events/day uniformly spread over 2 events/s, your system will suddenly be hit with 100 events/s, or even 10,000/s. Looking up the URL and recording the event will spike from 10ms to 1s or even 10s.
While your system records the event, the user waits. And waits. Often closing the browser tab without ever seeing your content.
Upgrading the database’s hardware is an expensive way to buy time, but it’ll work for a while. Eventually though, you’ll have to go asynchronous.
How Asynchronous Scales
With Asynchronous Processing, it becomes the responsibility of the Server to remember the Link Tracking event and process it later. Depending on your tech stack this can be done a lot of different ways including Threads, Callbacks, external queues and other forms of buffering the data until it can be processed.
The important part, from a scaling perspective, is that the user is redirected to the original URL as quickly as possible.
The user doesn’t care about Link Tracking, and with Asynchronous Processing you won’t make your users wait while you write to the database.
Making the event processing asynchronous is an important first step towards making a scalable system. In part 2 I will discuss how caching the URLs will improve the design further.