general
URL Shortener
Where does this short link go?
A hash-only table keyed by short code, with an index for the reverse lookup.
The simplest single-table design: a partition key and no sort key. Each item maps a short code to a long URL, with a click count that goes up by one in a single atomic update. The table is only ever read by GetItem on the code; an index on longUrl shows whether a URL already has a code, so the app can reuse it rather than create another.
The model
ShortLink
A short code mapping to a long URL.
- pk
- LINK#<code>
Attributes: code (S), longUrl (S), clicks (N), createdBy (S), createdAt (S), lastClickedAt (S), isDisabled (BOOL)
Access patterns
- GetItemResolve a short code
Fetch the long URL for a short code.
- Query · GSI1Find short code for URL
Check whether a given long URL already has a short code.
- UpdateItemIncrement click count
Atomic ADD on clicks when a short link is resolved.
Design notes
Why hash-onlywhy
Every read of the table is a GetItem by the full key, so there is no sort key to carry. Adding one would cost storage and buy nothing for these access patterns.
A static prefix on the codewhy
Every code is stored behind LINK#, so the key template starts with fixed text. A tool that finds an entity's rows by key prefix has something to match on: with a bare code as the key there is no prefix, and a begins_with on an empty string selects the whole table.
A GSI for the reverse lookupwhy
Without GSI1, finding an existing short code for a given long URL would require a full-table scan. With KEYS_ONLY projection the GSI is cheap and returns just the composite keys - enough to resolve via a follow-up GetItem on the base table if you need the full record.
Click counter uses ADDwhy
DynamoDB's ADD expression is atomic server-side. Multiple concurrent redirects never lose a click even without conditional writes or app-side locking.
isDisabled over deletetrade-off
Keeping disabled links with isDisabled set to true preserves analytics (click history) and avoids the footgun of a collision if someone later re-registers the same short code. Delete when you're sure.
Taught in the course
- The key is the address - GetItem needs the whole primary key: partition and sort.
- UpdateItem edits in place - UpdateItem changes named attributes and can increment a counter atomically.
- A different key for a different question - A secondary index re-keys your items so you can Query them on a new axis.
Fetch the long URL for a short code.
Choose an access pattern above, or build your own request. See what comes back and what it costs.
Write transactions, streams, tags and TTL are among the operations this browser build leaves out. dynoxide's native build has them.