Markdown Editor

URL Shortener System Design Template (Reference Design)

Capacity (KaTeX), API, base62 key generation and collisions, 301 vs 302, caching, click analytics, abuse protection, custom aliases, expiry, multi-region

सिस्टम डिज़ाइनपूर्णRFC 9110 (redirect status codes)designurlshortenermath
एडिटर में खोलें.md डाउनलोड करें

उपयोग कैसे करें: Use it when designing a short link service or preparing the classic interview problem. Fill the read-to-write ratio and retention first, since they set code length, storage and cache size. The main pitfall is launching without abuse controls and choosing 301 redirects that break analytics and takedowns.

प्रीव्यू

System Design: [URL shortener name]

Reference design for a URL shortening service that turns long URLs into short codes and redirects visitors at high volume and low latency. It covers capacity estimation, the public API, key generation (base62 encoding, counters, hashes and pre-generated keys, collision handling), the data model, the 301 versus 302 redirect trade-off under RFC 9110, caching, the click analytics pipeline, abuse and malicious URL protection, custom aliases, expiry and multi-region deployment. It follows the structure of the System Design Document template and is pre-filled with a worked design to adapt. Values marked Example are assumptions. Replace every [bracketed] value and every row marked Example.

Document control

FieldValue
Document ID[SDD-URL-001]
System / feature[Short link service]
Version[0.1]
Status[Draft / In review / Approved / Implemented / Superseded]
Author(s)[@author]
Reviewers[@reviewer-1], [@reviewer-2]
Last updatedYYYY-MM-DD
Classification[Internal]
Short domain[sho.rt]
Related[Capacity estimation worksheet CAP-EST-nnn], [Rate limiter design], [Threat model]

Approvals

RoleNameDecisionDate
Tech lead[@name][Approved / Changes requested]YYYY-MM-DD
Staff / principal engineer[@name][Decision]YYYY-MM-DD
SRE / operations[@name][Decision]YYYY-MM-DD
Security and trust and safety[@name][Decision]YYYY-MM-DD
Privacy (analytics)[@name][Decision]YYYY-MM-DD

Revision history

VersionDateAuthorChange summary
0.1YYYY-MM-DD[@name]First draft for design review
0.2YYYY-MM-DD[@name]Example: Moved from hashed codes to counter ranges with a keyed permutation
0.3YYYY-MM-DD[@name]Example: Default redirect changed from 301 to 302 so analytics and takedowns work
1.0YYYY-MM-DD[@name]Example: Approved

Contents

1. Overview

1.1 Problem statement

[Example: Product teams embed long tracking URLs in SMS, printed material and social posts. Long URLs break in some clients, cannot be updated after printing and give no click data. Teams currently use three external shorteners with different terms, no central takedown process and no data residency control.]

1.2 Proposed solution

[Example: A first-party shortener on a dedicated short domain. Clients create links through an authenticated API; the service assigns a 7-character base62 code from a pre-allocated counter range, passes the destination through a keyed permutation so codes are not sequential, checks the destination against URL reputation feeds and stores the mapping in a replicated key-value store. Visitors hit a stateless redirect tier that serves most lookups from an in-memory cache and answers with HTTP 302. Each redirect emits a click event to a message queue; a stream job aggregates clicks for the statistics API. Links can expire, be disabled by trust and safety, or carry a custom alias.]

1.3 Decisions requested from reviewers

IDQuestionRecommended optionSection
Q-01Example: How are codes generated?Counter ranges per server, encoded in base62 after a keyed permutation7.1, 10
Q-02Example: Which redirect status by default?302, with 301 available for links the owner marks permanent7.3
Q-03Example: Same long URL twice: same code or new code?New code per create request; optional dedupe per owner7.2
Q-04Example: Are expired codes ever reused?Never7.8
[Q-nn][Question][Option][Section]

2. Requirements

2.1 Functional requirements

IDRequirementPriority
FR-01Example: Create a short link for an http or https URL and return the codeMust
FR-02Example: Redirect a visitor from the short URL to the destinationMust
FR-03Example: Optional custom alias chosen by the ownerMust
FR-04Example: Optional expiry date or click limitShould
FR-05Example: Owner can disable a link; trust and safety can block itMust
FR-06Example: Click statistics per link per hour, by country and referrer domainShould
FR-07Example: Change the destination of a temporary (302) linkCould
[FR-nn][Requirement][Must / Should / Could]

2.2 Non-functional requirements

IDQualityTargetMeasured as
NFR-01Redirect latencyExample: p99 at or below 20 ms at the redirect tierServer timing
NFR-02Redirect availabilityExample: 99.99% monthlySynthetic probes from three regions
NFR-03Create latencyExample: p99 at or below 300 ms including reputation checkAPI timing
NFR-04DurabilityExample: No acknowledged link is ever lostReplication factor 3, backup restore test
NFR-05UnpredictabilityExample: Codes cannot be enumerated sequentiallyReview of 7.1
NFR-06TakedownExample: A blocked link stops redirecting within 60 s everywhereTest against cache TTLs
[NFR-nn][Quality][Target][Measurement]

2.3 Out of scope

  • [Example: link-in-bio pages and landing page builders]
  • [Example: QR code rendering (handled by the client libraries)]
  • [Example: user-level tracking across links; analytics are aggregate only]
  • [Item deferred, with the release that will take it]

3. Capacity estimation

3.1 Assumptions

InputSymbolValueSource
New links per monthWWExample: 100 millionForecast from current external shorteners
Read-to-write ratiorrExample: 100Click data from current shorteners
Peak-to-average ratiokkExample: 5Campaign launches
Retention of linksTTExample: 5 yearsProduct policy
Stored bytes per link incl. indexesssExample: 500 BSchema draft (average URL 200 characters)
Replication factorNNExample: 3Store configuration
Click event sizeeeExample: 200 BEvent schema
Usable redirects per instanceqqExample: 5 000 req/s at 60% CPULoad test

3.2 Request rates

A 30-day month has 2 592 000 seconds:

Qw,avg=1082 592 000≈38.6 creates/s,Qw,peak=38.6×5≈193 creates/sQ_{w,avg} = \frac{10^{8}}{2\,592\,000} \approx 38.6 \ \text{creates/s}, \qquad Q_{w,peak} = 38.6 \times 5 \approx 193 \ \text{creates/s}
Qr,avg=38.6×100≈3 858 redirects/s,Qr,peak=3 858×5≈19 290 redirects/sQ_{r,avg} = 38.6 \times 100 \approx 3\,858 \ \text{redirects/s}, \qquad Q_{r,peak} = 3\,858 \times 5 \approx 19\,290 \ \text{redirects/s}

Per day that is about 3.33 million creates and 333 million redirects.

3.3 Storage and key space

L=108×12×5=6×109 links,S=6×109×500 B=3 TB,S×N=9 TBL = 10^{8} \times 12 \times 5 = 6 \times 10^{9} \ \text{links}, \qquad S = 6 \times 10^{9} \times 500 \ \text{B} = 3 \ \text{TB}, \qquad S \times N = 9 \ \text{TB}

Base62 key space for code length ℓ\ell is 62ℓ62^{\ell}:

626≈5.68×1010,627≈3.52×101262^{6} \approx 5.68 \times 10^{10}, \qquad 62^{7} \approx 3.52 \times 10^{12}

Six characters would be 10.6% full after five years, which makes random codes collide often and leaves little room for growth. Seven characters are (6×109)/(3.52×1012)≈0.17%(6 \times 10^{9}) / (3.52 \times 10^{12}) \approx 0.17\% full after five years.

3.4 Cache and analytics

Caching the hot 20% of a day's redirects as an upper bound:

C=3.33×108×0.2×500 B≈33 GBC = 3.33 \times 10^{8} \times 0.2 \times 500 \ \text{B} \approx 33 \ \text{GB}

Click events:

Eday=3.33×108×200 B≈67 GB/day≈24 TB/year rawE_{day} = 3.33 \times 10^{8} \times 200 \ \text{B} \approx 67 \ \text{GB/day} \approx 24 \ \text{TB/year raw}

3.5 Summary

QuantityEstimateDesign consequence
Creates38.6/s average, 193/s peakSmall write tier; reputation check fits in budget
Redirects3 858/s average, 19 290/s peakStateless redirect tier with cache, 6 instances across 3 zones
Links after 5 years6 billion, 3 TB (9 TB replicated)Partitioned key-value store keyed by code
Code length7 base62 characters0.17% of key space used after 5 years
Cacheabout 33 GBOne small in-memory cache cluster per region
Click eventsabout 67 GB/dayQueue plus stream aggregation; raw events kept 90 days
Redirect egress19 290×50019\,290 \times 500 B ≈9.6\approx 9.6 MB/s at peakNot a constraint

4. API design

4.1 Endpoints

Method and pathPurposeAuth
POST /v1/linksCreate a link (optional alias, expiry, redirect type)API key or OAuth token
GET /v1/links/{code}Read link metadataOwner
PATCH /v1/links/{code}Change destination (302 links only), expiry or statusOwner
DELETE /v1/links/{code}Disable a link (code stays reserved)Owner
GET /v1/links/{code}/stats?from=&to=&granularity=hourAggregated clicksOwner
GET /{code} on the short domainRedirectPublic
POST /v1/reportsReport an abusive linkPublic, rate limited

4.2 Request and response examples

Create a link, then follow it from the short domain:

POST /v1/links HTTP/1.1
Authorization: Bearer [token]
Idempotency-Key: 6f1c2a9e-4b7d-4c1e-9a55-0d3f2b8e7c11
Content-Type: application/json

{"url": "https://www.example.com/spring-sale?utm_source=sms&utm_campaign=s26", "alias": null, "expires_at": "2027-03-31T23:59:59Z", "redirect": 302}
HTTP/1.1 201 Created
Location: https://api.sho.rt/v1/links/k7Qx2Lm
Content-Type: application/json

{"code": "k7Qx2Lm", "short_url": "https://sho.rt/k7Qx2Lm", "url": "https://www.example.com/spring-sale?utm_source=sms&utm_campaign=s26", "redirect": 302, "expires_at": "2027-03-31T23:59:59Z", "status": "active"}
GET /k7Qx2Lm HTTP/1.1
Host: sho.rt

HTTP/1.1 302 Found
Location: https://www.example.com/spring-sale?utm_source=sms&utm_campaign=s26
Cache-Control: private, max-age=60
Referrer-Policy: strict-origin-when-cross-origin

4.3 Errors and idempotency

SituationStatusProblem type
Destination not http or https, or longer than 2 048 characters400invalid-url
Destination flagged by reputation check422destination-blocked
Alias already taken or reserved409alias-unavailable
Create rate limit exceeded429rate-limited with Retry-After
Unknown code on the short domain404HTML page, no redirect
Expired or disabled link410HTML page explaining the link is no longer active
Blocked by trust and safety410 (451 when blocked for a legal reason)Warning page without the destination link

A retried POST with the same Idempotency-Key and body within 24 hours returns the original response; with a different body it returns 422. Keys are stored with the owner ID so two owners cannot collide.

5. Data model

5.1 Entities

Links are the core record; click aggregates and abuse reports hang off the code.

5.2 Storage choices

DataStoreKeyMain queriesWhy
LinksExample: Replicated key-value or wide-column store, partitioned by codecodeGet by code (redirect), conditional insertSingle-key reads at high rate, horizontal scale
Owner indexSame store, secondary tableowner_id, created_at descList an owner's linksAvoids scatter-gather
Dedupe index (optional)Same storeowner_id + url_hashFind existing code for a URLOnly when dedupe is enabled per owner
Click aggregatesColumnar analytics storecode, hourRange by time per codeCheap scans and compression
Raw click eventsMessage queue, then object storage for 90 daysTimeReprocessing, abuse investigationsNot on the redirect path
Abuse reportsRelational databasereport_idQueue for reviewersSmall, workflow-heavy

The link record is immutable except for status, expires_at and, for 302 links, long_url. Every change is written to an audit table with the actor.

6. High-level design

ComponentResponsibilityScales by
Edge / CDNTLS termination, DDoS absorption, optional short-TTL caching of redirectsProvider
Redirect serviceLook up code, check status and expiry, answer redirect, emit click eventStateless instances
Regional cacheHold hot code-to-URL mappings and negative entries for unknown codesMemory per node
Link storeDurable mapping, conditional inserts for codes and aliasesPartitions by code
Link APIValidate, authorise, check reputation, allocate code, writeStateless instances
Key allocatorHand out counter ranges to API instancesOne small replicated service
Click event queue and aggregatorDecouple analytics from redirectsPartitions
Periodic rescannerRe-check destinations against reputation feedsBatch workers

7. Detailed design

7.1 Key generation

Base62 uses the alphabet 0-9a-zA-Z (digits are values 0 to 9, lower case 10 to 35, upper case 36 to 61). Encoding repeatedly divides the number by 62 and maps remainders to characters, most significant first. For example 125=2×62+1125 = 2 \times 62 + 1 encodes as 21, and 11 157=2×622+55×62+5911\,157 = 2 \times 62^{2} + 55 \times 62 + 59 encodes as 2TX.

OptionHow it worksCollisionsEnumerationCoordinationNotes
Hash of URLTruncate a hash (for example SHA-256) of the URL, plus salt, to 7 charactersPossible; must check and retry with a new saltNot sequentialNoneSame URL gives same code unless salted per request
Random codeDraw 7 random base62 characters from a CSPRNGPossible; check and retryNot sequentialNoneSimple; collision rate rises with occupancy
Global counterSingle sequence, encode in base62NoneSequential, trivially enumerableEvery create hits the counterBottleneck and privacy problem
Counter rangesAllocator hands each API instance a block of IDs; instance encodes locallyNoneSequential unless permutedOne call per blockGaps when an instance dies holding a block
Pre-generated keysOffline job fills a table of unused random codes; API claims themNone at claim timeNot sequentialClaim must be atomicExtra table and refill job

Chosen: counter ranges (blocks of 1 000 000 IDs) with a keyed bijective permutation of the ID space [0,627)[0, 62^{7}) before encoding, for example a format-preserving encryption mode such as FF1 from NIST SP 800-38G. The permutation makes codes look random while preserving uniqueness; it is an obfuscation against casual enumeration, not access control, so private destinations still need authentication at the destination.

At the peak create rate of 193/s, one block lasts at least 106/193≈5 18110^{6} / 193 \approx 5\,181 s (about 86 minutes) even if a single instance served all creates. Losing an unused block wastes IDs, not correctness: the key space is 0.17% used after five years.

Collision handling: every write is a conditional insert ("put if absent") on code. With counter ranges a conflict indicates a bug or an alias clash, so the API raises an alert and allocates the next ID. With random or hashed codes the expected retries per insert are about the occupancy ratio, so 0.17% at five years. The birthday bound shows why the check is mandatory rather than optional: for nn random codes in a space of size MM, the chance of at least one collision is about 1−e−n2/(2M)1 - e^{-n^{2}/(2M)}, which is effectively 1 for n=6×109n = 6 \times 10^{9} and M=3.52×1012M = 3.52 \times 10^{12}.

7.2 Create flow

Normalisation lower-cases the scheme and host and removes default ports; it never rewrites the path or query, because those are meaningful to the destination. Dedupe (Q-03) is per owner and off by default, since two campaigns often need separate statistics for the same URL.

7.3 Redirects: 301 versus 302

RFC 9110 defines 301 (Moved Permanently, section 15.4.2) and 308 (Permanent Redirect, 15.4.9) as permanent and lists them among the status codes that are heuristically cacheable; 302 (Found, 15.4.3) and 307 (Temporary Redirect, 15.4.8) are temporary. 307 and 308 require the client to keep the request method; for a shortener visitors almost always send GET, so the difference matters little.

Aspect301 / 308 permanent302 / 307 temporary
Browser cachingBrowsers may cache the redirect for a long timeRevalidated per visit unless cache headers allow
Load on the serviceLower after the first visitEvery visit reaches the edge or service
Click analyticsRepeat visits invisibleEvery visit counted
Changing destination or takedownCached copies keep redirectingTakes effect at next visit or cache expiry
Search engine treatmentSignals a permanent moveSignals a temporary move

Chosen: 302 by default with Cache-Control: private, max-age=60, so NFR-06 (takedown within 60 s) holds and analytics stay complete. Owners can opt into 301 for links they declare permanent and will never edit; such links cannot change destination, and takedown relies on the warning page reaching visitors whose browsers have not cached the redirect.

7.4 Caching

  • Redirect tier cache: read-through cache keyed by code with TTL 60 s for active links. Status changes publish an invalidation event so blocked links leave every regional cache within seconds, with the TTL as the backstop.
  • Negative caching: unknown codes are cached for 30 s to absorb scanning bots without hitting the store.
  • Edge caching: when enabled, the redirect carries Cache-Control: max-age=60 instead of private (a private response must not be stored by a shared cache), so the CDN may cache 302 responses for the same 60 s, which cuts origin load during campaign spikes. Click counting then happens from edge logs for cached hits, or edge caching is disabled for links with analytics enabled; choose one and record it in 12.1.
  • Hit ratio: with a 90% cache hit ratio the store serves about 19 290×0.1≈1 92919\,290 \times 0.1 \approx 1\,929 reads/s at peak.

7.5 Analytics pipeline

The redirect service writes a click event to a local buffer and returns the redirect; a background sender publishes batches to the click event queue (see Message queue design (system-design/design-message-queue)). Losing a few events during a crash is accepted: analytics are at-least-once from the queue onwards and best effort before it.

StageProcessingOutput
Redirect serviceBuild event: code, timestamp, country from IP, referrer host, user agent class, truncated IPEvent batch
QueuePartitioned by code, retained 7 daysDurable stream
Stream aggregatorCount per code per hour; unique visitors estimated with HyperLogLog sketches; deduplicate by event IDHourly rows
Columnar storeHourly aggregates kept for the life of the linkStatistics API
Object storageRaw events kept 90 days, then deletedReprocessing and investigations

Privacy: no cookies are set on the short domain; IP addresses are truncated before storage and never exposed through the API; aggregates below 10 clicks per bucket are shown as "fewer than 10" to limit re-identification.

7.6 Abuse and malicious URL protection

ControlWhenEffect
Scheme allow list (http, https only)CreateBlocks javascript:, data: and file: destinations
Reputation lookup against a URL threat feed (for example Google Safe Browsing, subject to its terms) and an internal block listCreate, and rescans at 1 h, 24 h and weeklyFlags malware, phishing and unwanted software
Rate limits per account, per IP and per destination domainCreateLimits bulk generation; see Rate limiter design (system-design/design-rate-limiter)
Self-referencing and chained shorteners refusedCreatePrevents redirect loops and laundering through other shorteners
Warning interstitialRedirect, for flagged or newly created links from unverified accountsVisitor sees destination host and a warning
Public report endpoint and trust and safety consoleAny timeDisable, block or restore with audit trail
No server-side fetch of the destination outside an isolated scannerAlwaysPrevents server-side request forgery from the API tier

A blocked link returns a warning page that does not render the destination as a clickable link. Repeat offenders have all their links disabled.

7.7 Custom aliases

  • Allowed characters [A-Za-z0-9_-], length 4 to 30 (Example); case is significant, matching generated codes.
  • A reserved list blocks paths used by the service (api, login, help), brand names and offensive words.
  • Aliases share the code key space and use the same conditional insert, so an alias can never shadow a generated code.
  • Short aliases (4 to 6 characters) are limited to paid plans to reduce squatting.

7.8 Expiry and deletion

Expiry is checked at read time (expires_at or click limit reached) and the service returns 410. A daily job marks expired links and removes them from caches. Codes are never reused: a reused code would send old printed or bookmarked links to a new destination, which is both a safety and a fraud risk. Deleting a link removes the destination after 30 days but keeps the code tombstoned.

7.9 Multi-region

  • Reads: each region has a redirect tier, cache and a full replica of the link store; redirects never leave the region.
  • Writes: creates are accepted in any region. Counter blocks are allocated per region from disjoint ranges, so regions never collide on generated codes. Aliases use a conditional insert in a strongly consistent global table, accepting higher create latency for aliases only.
  • Replication lag: a link created in region A and opened in region B before replication finishes would miss. On a local miss the redirect service asks the home region encoded in the code's block metadata before returning 404, and caches the result.

8. Scalability and performance

ConcernApproachLimit before redesign
Redirect rateStateless tier: ⌈19 290/5 000⌉=4\lceil 19\,290 / 5\,000 \rceil = 4 instances, ⌈4×3/2⌉=6\lceil 4 \times 3/2 \rceil = 6 across three zonesExample: about 10 times growth by adding instances
Hot linksCache plus optional edge cachingOne link at campaign peak
Store growthPartitioned by code, 9 TB replicated after 5 yearsTens of TB without change
Create rateLocal ID blocks, no per-create coordinationReputation service quota first
Analytics volumeQueue partitions and hourly aggregationRaw retention cost

Latency budget for a redirect (target p99 20 ms at the service):

StepBudget
Parse and validate code0.1 ms
Cache lookup (same zone)1 ms
Store lookup on cache miss (10% of requests)10 ms
Status and expiry checks, build response0.2 ms
Enqueue click event (local buffer)0.1 ms
Headroom8.6 ms

9. Reliability, security and operations

9.1 Failure modes

FailureImpactDetectionMitigation
Cache cluster downStore load rises ten timesCache error rateStore sized for 50% hit ratio during incidents; request coalescing
Store partition unavailableSome codes cannot resolveError rate per partitionReplicas in three zones; serve stale cache entries for up to 1 h
Key allocator downNo new blocksAllocation errorsInstances hold two blocks; creates continue for hours
Reputation service downCreates cannot be checkedTimeout rateCreate with pending_review status and warning interstitial until checked
Analytics queue downClick data delayedBuffer depthLocal buffer with bounded size; drop oldest with a counter
[Failure][Impact][Signal][Mitigation]

9.2 Security and abuse

ThreatControl
Phishing and malware distribution7.6 controls, rescans, interstitials, fast takedown
Enumeration of private linksKeyed permutation, 7-character codes, negative caching, rate limits on 404s
Open redirect used against the parent brandSeparate short domain, never the main application domain
Account takeover to edit destinationsStrong authentication for owners, audit log, notification on destination change
Destination change after approval (bait and switch)Destination edits trigger a new reputation check and interstitial for 24 h
[Threat][Control]

Record these in the threat model (security/threat-model).

9.3 Observability

SignalMetric or logAlert threshold
Redirect latencyp99 per regionAbove 20 ms for 10 min
Redirect errors5xx shareAbove 0.1% for 5 min
404 rateUnknown codes per secondTripling vs. 7-day baseline (scanning)
Blocked createsShare flagged by reputationSudden rise (campaign of abuse)
Takedown latencyTime from block to last served redirectAbove 60 s

9.4 Cost estimate

ItemUnit costQuantityMonthly cost
Redirect and API instances[USD per instance-month]Example: 6 redirect + 3 API per region x 2 regions[USD]
Link store[USD per TB-month and per million reads]9 TB after 5 years[USD]
Cache[USD per node-month]Example: 3 nodes per region[USD]
Analytics queue, stream and store[USD]67 GB/day raw[USD]
Reputation feed[Licence or quota cost]3.3 million lookups/day plus rescans[USD]
Total[USD]

10. Trade-offs and alternatives

DecisionOptionsChosenWhyWhat we give up
Code generationHash; random; global counter; counter ranges; pre-generatedCounter ranges with permutationNo collisions, no per-create coordinationPermutation key is a secret to manage
Code length6; 7; 8 characters70.17% full after 5 yearsOne more character than the minimum
Default redirect301; 302; 307302Analytics, edits and takedown workMore traffic than permanent redirects
StoreRelational; key-valueKey-value partitioned by codeSingle-key access at scaleSecondary queries need extra tables
AnalyticsSynchronous counter update; async eventsAsync eventsRedirect latency unaffectedCounts lag by minutes
Code reuse after expiryReuse; neverNeverOld links never go to a new destinationKey space slowly consumed
[Decision][Options][Chosen][Why][Cost]

11. Delivery plan and risks

11.1 Milestones

MilestoneScopeExit criterionTarget date
M1Create and redirect in one region, internal usersp99 redirect under 20 ms in load test at 2x peakYYYY-MM-DD
M2Abuse controls, reputation checks, trust and safety consoleRed-team test of phishing creation blockedYYYY-MM-DD
M3Analytics pipeline and statistics APICounts within 1% of redirect logsYYYY-MM-DD
M4Second region, migration of links from external shortenersRedirect parity test for all migrated codesYYYY-MM-DD

11.2 Rollout and rollback

[Example: Launch with internal teams only, then allow external accounts by plan tier. Migrated links from external shorteners are imported with their original codes on a separate path prefix and verified one by one before the old shortener's domain is pointed at the new service.]

11.3 Risks

IDRiskLikelihoodImpactMitigationOwner
R-01Example: Short domain added to blocklists after abuseMediumHigh7.6 controls, monitoring of blocklist status, abuse contact published[@name]
R-02Example: Permutation key leaked, codes become predictableLowMediumKey in a secrets manager; codes remain unique even if predictable[@name]
R-03Example: Analytics privacy complaintLowMediumAggregate-only data, truncated IPs, documented retention[@name]
[R-nn][Risk][L / M / H][L / M / H][Mitigation][@name]

12. Appendices

12.1 Open questions

IDQuestionOwnerDue
OQ-01Example: Edge caching of redirects, or complete click counts?[@name]YYYY-MM-DD
OQ-02Example: Do enterprise owners need their own branded short domains?[@name]YYYY-MM-DD
[OQ-nn][Question][@name]YYYY-MM-DD

12.2 Glossary

TermMeaning
CodeThe short path segment that identifies a link
AliasA code chosen by the owner instead of generated
Base62Encoding with 62 symbols: ten digits and two cases of 26 letters
Keyed permutationReversible mapping of the ID space controlled by a secret key
Negative cachingCaching the fact that a key does not exist
InterstitialPage shown before redirecting, with a warning or confirmation
[Term][Meaning]

12.3 References

ReferenceUse
RFC 9110 HTTP Semantics (June 2022), sections 15.4.2, 15.4.3, 15.4.8, 15.4.9Redirect status codes and cacheability
RFC 9457 Problem Details for HTTP APIsError format
NIST SP 800-38G, format-preserving encryption (FF1)Keyed permutation option in 7.1
URL reputation provider documentation and terms7.6
Capacity estimation worksheet (system-design/back-of-envelope-estimation)Method for section 3
System design document (system-design/system-design-document)Parent structure

Standard and licence note

Based on common industry practice for URL shortening services and on the HTTP specifications cited in 12.3. This is a reference design to adapt, with illustrative numbers. Original text written for this collection; no text from the cited specifications is reproduced. Check the current versions of the RFCs and the terms of any reputation service before use. Template licence: MIT.

संबंधित टेम्पलेट