backendgym backendgym · projects Sign in with GitHubSign in

projects /11-short-links

# Short links, counted

A grocery shop's Thursday SMS carries a 212-character link that phones cut in half. Build the short links its marketing team sends instead, and count every click, from an empty repository to a public address.

Warmup ~10h any stack 3 milestones

series The URL shortener · step 1 of 4

practises http, rest, authentication, load-testing

short-links / spec.md v1.0

Thursday's SMS

Pantry sells groceries online. Every Thursday the marketing team sends the week's offers by SMS to 40,000 customers, and the link in the message is the full address of the offers page: 212 characters. Some phones cut it in half, and its length makes every message cost two SMS instead of one.

Maya runs the campaigns. She wants the team's own short links, an address of your service followed by a code of at most eight letters and digits, and she wants to know how many times each one was opened. On Friday that number is how she shows the campaign worked.

What it has to put up with

A link is created once and opened thousands of times, most of them in the hour after the SMS goes out. Once the message is sent the link can't be fixed: it is already on 40,000 phones, so it has to keep working through every deploy after that.

Only the team may create links. A shortener anyone can use gets found and filled with phishing links within weeks.

Not the job

No accounts per person, no custom codes, no expiry, and no analytics beyond the count: who clicked and when can wait.

Language, framework, database, how codes are made, how the service knows the team from everyone else and where it runs 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 · Short links that redirect

The team can shorten an address, and the short link sends anyone to it.

  1. R1
    The team can turn an http or https address with a host, up to 2,048 characters, into a short link whose code is at most eight letters and digits. Any other address is refused and creates nothing.
  2. R2
    Opening a short link sends the browser to exactly the address it was made from, query string included. A code that was never issued answers 404.
  • D1 R2 , not recorded yet

    Shorten https://pantry.test/offers?utm_source=sms&utm_campaign=thursday&q=caf%C3%A9. Request the short link without following redirects and read the status and the Location header. Then request a code you never issued.

    expectA redirect status whose Location is the long address character for character, and a 404 for the code you never issued.

  • D2 R1 , not recorded yet

    Try to shorten javascript:alert(1), ftp://files.pantry.test/a, an empty address and an https address of 2,049 characters. Then list the team's links.

    expectAll four are refused with a client error, and none of them became a link.

M2 · Only the team creates, and every click counts

Creating links and reading counts need the team's credential, and the count matches every click.

  1. R3
    hidden until you ask the stakeholder
    ask the stakeholder

    start the project to ask

  2. R4
    Every opening of a short link is counted, and the team can see all its links with their counts.
  3. R5
    Only the team can create links and read counts. Anyone can open a short link.
  • D3 R5 , not recorded yet

    Without the team's credential, and then with a wrong one, try to create a link to https://evil.test/ and to read an existing link's count. Then open that existing short link with no credential at all.

    expectEvery create and every count request is refused, no link to evil.test exists, and the short link still redirects.

  • D4 R4 , not recorded yet

    Read one link's count. Request that short link 1,000 times, 50 at a time, without following the redirect, and read the count again once every response is back.

    expectThe count went up by exactly 1,000.

  • D5 R4 , not recorded yet

    Put one short link on a page or in a chat message. In an ordinary desktop browser, click it, let the long address load, and go back; do that five times. Then read the link's count.

    expectThe count went up by five.

M3 · Live at a public address

A public HTTPS address that survives deploys, with a baseline for how fast it redirects.

  1. R6
    The service runs at a public HTTPS address, and a link created before a deploy still redirects after it, with its count intact.
  • D6 R6 , not recorded yet

    Shorten an address on your public deployment and open the short link on a phone on mobile data. Deploy any change the way you normally deploy and confirm the new version is live, then open the same short link on the phone again.

    expectBoth openings land on the long address over HTTPS, and the link's count went up by two.

  • D7 R6 , 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 number of requests that failed.

    expectNo request fails. The p99 is your baseline: nothing in this build 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

  • ▸Get one short link redirecting before anything else. Almost every drill here is about the redirect.
  • ▸Deploy as soon as M1 works. A first deploy is easier with two routes than with ten.
  • ▸Keep whatever you use for D4's load, a script or a tool: D7 needs one against your public address.

Done when

Every drill above passes, and:

  • The README says how to run it locally, how it is deployed and how the team creates a link.
  • No password, key or connection string is in the repository.
Solutions

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