URL shortener
the classic warm-up: a write path that mints keys, a read path that must be fast
source · 10-url-shortener.arch
# URL shortener — the classic warm-up: a write path that mints keys, a read path that must be fast actor user "User" external browser "Browser" system shortener "URL shortener" { gateway lb "Load balancer" { transit } service api "Shortener API" tech Go service keygen "Key generator" tech Go cache redis "Hot links" tech Redis owned_by api datastore urls "Links DB" tech PostgreSQL owned_by api job cleaner "Expiry sweeper" tech Go api calls keygen over gRPC "next unique key" api reads redis over RESP "302 fast path" api reads urls over SQL "cache miss" api writes urls over SQL "new link" api writes redis over RESP "warm the cache" cleaner writes urls over SQL "drop expired" } user calls shortener.api over HTTPS via shortener.lb "shorten · redirect" env prod "Production" { cluster k8s "Kubernetes" nodes 3 cpu 8 mem 32Gi { run shortener.api replicas 4 cpu 0.5 mem 512Mi run shortener.keygen replicas 2 cpu 0.25 mem 256Mi run shortener.cleaner replicas 1 } managed cache_svc "Managed Redis" { run shortener.redis } managed pg "Managed Postgres" { run shortener.urls } }
archcode: "0.2"
objects:
- id: user
kind: actor
name: User
- id: browser
kind: external
name: Browser
- id: shortener
kind: system
name: "URL shortener"
- id: shortener.lb
kind: gateway
name: "Load balancer"
parent: shortener
attrs:
transit: []
- id: shortener.api
kind: service
name: "Shortener API"
parent: shortener
attrs:
tech: [Go]
- id: shortener.keygen
kind: service
name: "Key generator"
parent: shortener
attrs:
tech: [Go]
- id: shortener.redis
kind: cache
name: "Hot links"
parent: shortener
attrs:
tech: [Redis]
owned_by: [api]
- id: shortener.urls
kind: datastore
name: "Links DB"
parent: shortener
attrs:
tech: [PostgreSQL]
owned_by: [api]
- id: shortener.cleaner
kind: job
name: "Expiry sweeper"
parent: shortener
attrs:
tech: [Go]
- id: prod
kind: env
name: Production
- id: prod.k8s
kind: cluster
name: Kubernetes
parent: prod
attrs:
nodes: ["3"]
cpu: ["8"]
mem: [32Gi]
- id: prod.cache_svc
kind: managed
name: "Managed Redis"
parent: prod
- id: prod.pg
kind: managed
name: "Managed Postgres"
parent: prod
relations:
- from: api
verb: calls
to: keygen
over: gRPC
label: "next unique key"
- from: api
verb: reads
to: redis
over: RESP
label: "302 fast path"
- from: api
verb: reads
to: urls
over: SQL
label: "cache miss"
- from: api
verb: writes
to: urls
over: SQL
label: "new link"
- from: api
verb: writes
to: redis
over: RESP
label: "warm the cache"
- from: cleaner
verb: writes
to: urls
over: SQL
label: "drop expired"
- from: user
verb: calls
to: shortener.api
over: HTTPS
via: [shortener.lb]
label: "shorten · redirect"
placements:
- host: prod.k8s
run: shortener.api
attrs:
replicas: ["4"]
cpu: ["0.5"]
mem: [512Mi]
- host: prod.k8s
run: shortener.keygen
attrs:
replicas: ["2"]
cpu: ["0.25"]
mem: [256Mi]
- host: prod.k8s
run: shortener.cleaner
attrs:
replicas: ["1"]
- host: prod.cache_svc
run: shortener.redis
- host: prod.pg
run: shortener.urls
{
"archcode": "0.2",
"objects": [
{
"id": "user",
"kind": "actor",
"name": "User"
},
{
"id": "browser",
"kind": "external",
"name": "Browser"
},
{
"id": "shortener",
"kind": "system",
"name": "URL shortener"
},
{
"id": "shortener.lb",
"kind": "gateway",
"name": "Load balancer",
"parent": "shortener",
"attrs": {
"transit": []
}
},
{
"id": "shortener.api",
"kind": "service",
"name": "Shortener API",
"parent": "shortener",
"attrs": {
"tech": [
"Go"
]
}
},
{
"id": "shortener.keygen",
"kind": "service",
"name": "Key generator",
"parent": "shortener",
"attrs": {
"tech": [
"Go"
]
}
},
{
"id": "shortener.redis",
"kind": "cache",
"name": "Hot links",
"parent": "shortener",
"attrs": {
"tech": [
"Redis"
],
"owned_by": [
"api"
]
}
},
{
"id": "shortener.urls",
"kind": "datastore",
"name": "Links DB",
"parent": "shortener",
"attrs": {
"tech": [
"PostgreSQL"
],
"owned_by": [
"api"
]
}
},
{
"id": "shortener.cleaner",
"kind": "job",
"name": "Expiry sweeper",
"parent": "shortener",
"attrs": {
"tech": [
"Go"
]
}
},
{
"id": "prod",
"kind": "env",
"name": "Production"
},
{
"id": "prod.k8s",
"kind": "cluster",
"name": "Kubernetes",
"parent": "prod",
"attrs": {
"nodes": [
"3"
],
"cpu": [
"8"
],
"mem": [
"32Gi"
]
}
},
{
"id": "prod.cache_svc",
"kind": "managed",
"name": "Managed Redis",
"parent": "prod"
},
{
"id": "prod.pg",
"kind": "managed",
"name": "Managed Postgres",
"parent": "prod"
}
],
"relations": [
{
"from": "api",
"verb": "calls",
"to": "keygen",
"over": "gRPC",
"label": "next unique key"
},
{
"from": "api",
"verb": "reads",
"to": "redis",
"over": "RESP",
"label": "302 fast path"
},
{
"from": "api",
"verb": "reads",
"to": "urls",
"over": "SQL",
"label": "cache miss"
},
{
"from": "api",
"verb": "writes",
"to": "urls",
"over": "SQL",
"label": "new link"
},
{
"from": "api",
"verb": "writes",
"to": "redis",
"over": "RESP",
"label": "warm the cache"
},
{
"from": "cleaner",
"verb": "writes",
"to": "urls",
"over": "SQL",
"label": "drop expired"
},
{
"from": "user",
"verb": "calls",
"to": "shortener.api",
"over": "HTTPS",
"via": [
"shortener.lb"
],
"label": "shorten · redirect"
}
],
"placements": [
{
"host": "prod.k8s",
"run": "shortener.api",
"attrs": {
"replicas": [
"4"
],
"cpu": [
"0.5"
],
"mem": [
"512Mi"
]
}
},
{
"host": "prod.k8s",
"run": "shortener.keygen",
"attrs": {
"replicas": [
"2"
],
"cpu": [
"0.25"
],
"mem": [
"256Mi"
]
}
},
{
"host": "prod.k8s",
"run": "shortener.cleaner",
"attrs": {
"replicas": [
"1"
]
}
},
{
"host": "prod.cache_svc",
"run": "shortener.redis"
},
{
"host": "prod.pg",
"run": "shortener.urls"
}
]
}