backendgym backendgym · projects Sign in with GitHubSign in

projects /12-short-links-at-campaign-speed

# Short links, at campaign speed

Christmas offers go out to 400,000 phones at noon, and the short link waits ten seconds and gives up. Make your step 1 service keep up at 500 openings a second without losing a click, and let the team take a wrong link down.

Intermediate ~12h any stack 3 milestones

series The URL shortener · step 2 of 4

Builds on step 1: it starts from the repository you ship there.

practises caching, locking, percentiles, graceful-shutdown

short-links-at-campaign-speed / spec.md v1.0

Starts from the repository you shipped in step 1, Short links, counted.

Christmas Thursday

Over the year Pantry's customer list grew to 400,000. For the Christmas offers the team sent the SMS and an app notification at the same moment, at noon, and the short link in both was opened about 500 times a second for the first few minutes. Most of those requests waited ten seconds and gave up. Customers saw a blank page, and on Friday Maya's count was far below the sales.

The same afternoon a second link went out with the wrong price on panettone. The team wanted to take it down, and the only way was a deploy.

What has to change

At 500 openings a second on one link, nothing fails and nobody waits the way they did at Christmas. Every opening that got a redirect is still counted, including the ones answered while a deploy replaces the service, though the count may trail the clicks by up to a minute. And the team can disable a link: ten seconds later, opening it says the offer has ended.

500 a second is measured on your machine, with the service set up as it runs in production: the same build and settings you deploy, with its database running on your machine next to it. The load test may run on the same machine. A free host may not take that rate, and the host is not what this step is about. Against your public address you measure at 50 a second, as in step 1.

Not the job

No second instance, no changing where a link goes, no expiry, and no history of who clicked.

How the redirect gets faster, how clicks reach the count and how a disable reaches the redirect are yours to choose. Write the choices down in DESIGN before you build.

The work, in 3 milestones

Each milestone says what must be true and the drill that proves it. You close a milestone when its drills pass.

M1 · A number for the campaign

You know what the service you shipped in step 1 does under a campaign's load.

  • D1 R1 , not recorded yet

    Before changing anything, run the service on your machine as it runs in production, create a short link and request it 500 times a second for 60 seconds without following redirects. Write down the p99, the requests that failed, and any your tool could not send in time.

    expectYou have the baseline: the p99 and the failures of the service you shipped in step 1. Nothing sets a target for it.

M2 · Redirects that keep up

One link takes 500 openings a second, every click still counts, and the team can take a link down.

  1. R1
    Opened 500 times a second for 60 seconds, one short link answers every request without failing and without the wait D1 shows, measured on your machine with the service set up as it runs in production.
  2. R2
    Every opening that got a redirect is counted, including those answered while a deploy was replacing the service.
  3. R3
    The count the team reads may trail the clicks by up to one minute, never more.
  4. R4
    The team can disable a link. From ten seconds after that, opening it answers 410 with a page saying the offer has ended, and is not counted.
  • D2 R1 , not recorded yet

    After your change, run D1's load again: the same link, 500 requests a second for 60 seconds, on the same machine.

    expectYour tool sent all 30,000 requests and none failed. Put the p99 next to D1's, say what each opening no longer waits on, and what gave way first on your machine.

  • D3 R2 , not recorded yet

    On your machine, read one link's count. Request that short link 1,000 times, 50 at a time, without following the redirect. Read the count again one minute after the last response.

    expectThe count went up by exactly 1,000.

  • D4 R4 , not recorded yet

    On your machine, request one link 50 times a second for 30 seconds without following redirects, keeping each response's time and status. At second 10, disable the link and note the time. Then open it in a browser, and read its count a minute after the load ends.

    expectNo redirect arrives more than ten seconds after the disable, every response after that is a 410, the browser shows that the offer has ended, and the count went up by exactly the number of redirects received.

M3 · Live, through a deploy

The public service loses no click when it is replaced, and step 1's links still work.

  1. R5
    What step 1 promised still holds: links made before this step redirect, only the team creates links, reads counts and disables them, and the service runs at its public HTTPS address.
  • D5 R2 , not recorded yet

    Against your public address, request one link 50 times a second for 60 seconds, and deploy a change the usual way while it runs. Count the redirects received, and read the count a minute after the end. Requests that fail during the deploy are allowed: they are not clicks.

    expectThe count went up by exactly the number of redirects received.

  • D6 R5 , not recorded yet

    On a phone on mobile data, open a short link you created in step 1. Then, without the team's credential and then with a wrong one, try to disable it.

    expectIt lands on its long address over HTTPS, and both attempts to disable it are refused. If no link from step 1 survived, that is what this drill found.

  • D7 R1 , not recorded yet

    Against your public address, request one short link 50 times a second for 60 seconds without following redirects, and write down the p99 and the requests that failed.

    expectNo request fails. Put the p99 next to step 1's D7: nothing here sets a target for it.

Questions for the stakeholder

They reveal no requirement, but the answers shape the design.

start the project to ask

Technical guidance

  • ▸Run D1 before changing anything. Where the time goes decides what to change.
  • ▸Measure every change with the same rate, duration and link, on the same machine.
  • ▸Keep the load test in your repository: D5 and D7 run it against your public address.

Done when

Every drill above passes, and:

  • The README says how to run the load test on your machine and against the public address.
  • No password, key or connection string is in the repository.
Solutions

No solutions published yet. Ship the project and yours will be the first.