Shlink
Self-hosted URL shortener - short links on your domain, full REST API, analytics that are yours.
One-click deploy, from $13/mo on a Miget plan.
Shlink is a self-hosted URL shortener with the features the paid services gate: short links on your own domain, a full REST API, QR codes, rich visit analytics (with optional GeoIP), tags, and device-based redirect rules. The server handles the redirects and exposes the API on port 5000.
A managed Postgres holds every link and visit, so the app is stateless. Shlink ships no UI of its own - you drive it with the REST API, the CLI, or the Shlink Web Client (the official hosted client at app.shlink.io talks to your server from your browser, or self-host the client image).
The value is in the metering: hosted shorteners cap links and clicks aggressively and charge to lift the caps. Shlink is one flat plan with unlimited links, your own branded domain, and the analytics sitting in a database you own.
Upstream project: Shlink
#what you get
- Short links on your own custom domain
- Full REST API plus a CLI for automation
- QR codes, tags, and device/geo redirect rules
- Visit analytics with optional MaxMind GeoIP
- All link and visit data in managed Postgres - stateless app
- MIT licensed, unlimited links, no per-click billing
#topology
| Service | Role | Public |
|---|---|---|
| shlink | redirects + REST API (:5000) | yes |
| db | managed Postgres (links + visits) | no |
#miget sizing
// this stack needs
1.5 GiB RAM · 5 GB disk · 2 services
The RoadRunner-based server is happy in 512 MiB. Postgres holds links and visit rows, so size disk to your click volume and retention.
Hobby - recommended fit
$13/mo
1 vCPU · 2 GiB · 50 GiB disk
Headroom for your own apps: 2 GiB at $19/mo
Professional - production
$22/mo
1 vCPU · 2 GiB · 10 GiB disk
Dedicated resources, production SLOs - plan details
One Miget plan is a fixed pool of compute - the whole stack (managed databases included) deploys inside it, and anything left over runs your other apps. No per-service or per-seat math.
#vs. the managed service
What the hosted equivalents charge, against the flat Miget plan this stack fits on. Prices as of June 2026, sources linked.
| Service | Plan | Monthly | What you get |
|---|---|---|---|
| Shlink on Miget ★ | 2 GiB plan | $13 | this whole stack, flat - no usage meters, and room left for your own apps |
| Dub | Business | ~$75 | $75/mo |
| Bitly | Core | ~$10 | $10/mo for just 100 branded links |
| Short.io | Hobby | ~$5 | $5/mo; paid tiers scale with clicks |
Shorteners cap links and clicks aggressively; Shlink is unlimited on your own domain.
#vs. other PaaS
Estimated monthly cost of running this exact stack (1.5 GiB RAM, 5 GB disk, 2 containers) elsewhere, from published June 2026 rates.
| Platform | Est. monthly | Notes |
|---|---|---|
| Miget ★ | $13 flat | compose stacks first-class: one deploy, dedicated vCPU, managed Postgres/Valkey, volumes and TLS all included in the plan |
| Heroku | ~$75 | no volumes; nothing between 1 GB ($50) and 2.5 GB ($250) dynos - 2 GB containers cost far more than shown |
| DO App Platform | ~$23 | no persistent volumes - stateful containers need managed DBs/Spaces (base $5 Spaces included here) |
| Render | ~$20 | per-service instances (0.5 GB $7, 2 GB $25) - every container is its own paid service |
| Railway | ~$16 | usage-based ($10/GB RAM-mo); vCPU billed separately at $20/vCPU-mo on top |
| Fly.io | ~$10 | cheapest sticker price - but burstable shared CPUs (1/16 core; dedicated vCPUs cost ~2-3×), no compose deploys (one app per container, manual wiring), managed DBs billed extra |
Estimates assume RAM fully allocated at published on-demand rates - and sticker price isn't the whole comparison: the cheaper rows buy burstable shared CPUs, per-service wiring instead of a compose deploy, and managed databases billed separately. Heroku and DO App Platform have no persistent volumes at all - stateful stacks like this one need workarounds there.
#deploy it
On Miget
- Create a Compose Stack in app.miget.com pointing at the templates repository
- Set the stack path to
shlink -
Set the required variables:
DEFAULT_DOMAIN, the short domain (the app’s https domain)INITIAL_API_KEY, your first API key, created on startup
- Deploy. Miget layers
compose.miget.yaml(RAM, privacy, volumes, managed services) automatically
Locally first?
Every template is portable, vanilla Docker Compose - the Miget overrides are ignored locally:
git clone https://github.com/deployable-sh/stacks
cd miget-compose-templates/shlink
docker compose up -d Same files, same behavior. The template README covers connection strings and scaling notes.
#faq
What does this save vs Bitly or Short.io?
Bitly’s Core plan is $10/month for just 100 branded links a month, and Short.io and Dub meter the same way. Shlink is one ~$13/month plan with unlimited links, your own domain, and the analytics on your own infrastructure.
There is no admin UI in the container - how do I manage it?
Shlink is API-first. Use the REST API, the shlink-cli, or the Shlink Web Client - point the official hosted client at app.shlink.io (it runs in your browser against your server) or self-host the shlinkio/shlink-web-client image.
Do I get geographic visit stats?
Yes, if you set a free MaxMind GeoLite2 license key. Shlink then resolves visits to country and city and exposes the breakdown through the API and web client.
Ship Shlink today
One compose stack, 1.5 GiB of RAM, from $13/month flat, and it runs on your laptop with the same files.