Shlink vs YOURLS: Which URL Shortener to Self-Host?
Quick Verdict
Shlink is the better choice for most people in 2026. It has a modern API-first architecture, supports PostgreSQL, MySQL, and SQLite, and runs on an async PHP runtime that handles high traffic without breaking a sweat. If you need to shorten URLs programmatically — from scripts, CI pipelines, or other applications — Shlink is the clear winner.
YOURLS wins if you want a dead-simple web UI, a massive plugin ecosystem, and don’t care about API design. It’s been around since 2009 and has a battle-tested community. But its MySQL-only requirement and traditional LAMP architecture show their age.
Overview
Shlink is a modern, API-first URL shortener built in PHP on top of Swoole or RoadRunner for asynchronous request handling. Created by Alejandro Celaya, it’s designed for developers who want to integrate URL shortening into automated workflows. It ships as a headless API service — there’s no built-in web UI, though the separate Shlink Web Client fills that gap. Licensed under Apache 2.0.
YOURLS (Your Own URL Shortener) is one of the oldest self-hosted URL shorteners, first released in 2009. It follows the traditional LAMP model: PHP served through Apache or Nginx, backed by MySQL. Its strength is simplicity — a functional admin UI ships out of the box, and a large plugin ecosystem extends it in every direction. Licensed under MIT.
Both are PHP, both are actively maintained, and both get the job done. The difference is architectural philosophy.
Feature Comparison
| Feature | Shlink | YOURLS |
|---|---|---|
| Architecture | Async PHP (Swoole/RoadRunner) | Traditional LAMP |
| API | Full REST API, API-first design | Basic API, UI-first design |
| Built-in Web UI | No (separate Shlink Web Client) | Yes |
| Database Support | PostgreSQL, MySQL, MariaDB, SQLite, MS SQL | MySQL / MariaDB only |
| Custom Slugs | Yes | Yes |
| QR Code Generation | Built-in per short URL | Via plugin |
| Visit Tracking | Detailed (location, referrer, device, bot detection) | Basic (referrer, timestamp) |
| Bot Detection | Built-in, filters bot traffic from stats | Via plugin |
| Multi-domain Support | Native (multiple short domains, one instance) | No (one domain per instance) |
| Tag System | Built-in tagging and filtering | Via plugin |
| CLI Tool | Full CLI for all operations | Limited CLI |
| Import from Other Services | Yes (Bitly, YOURLS, CSV) | No |
| Plugin Ecosystem | Limited (designed for API extension) | Large (200+ community plugins) |
| Authentication | API key based | Cookie-based admin, API signature |
| Docker Support | Official image, well-maintained | Official image |
| License | Apache 2.0 | MIT |
| GitHub Stars | ~3,200+ | ~10,500+ |
Docker Compose: Shlink
This configuration runs Shlink with PostgreSQL as the database backend and the Shlink Web Client for a browser-based management UI.
Create a docker-compose.yml:
services:
shlink:
image: shlinkio/shlink:4.3.1
restart: unless-stopped
ports:
- "8080:8080"
environment:
# The short domain visitors will use (no protocol prefix)
DEFAULT_DOMAIN: links.example.com
# Set to true if your short domain uses HTTPS
IS_HTTPS_ENABLED: "true"
# Database connection
DB_DRIVER: postgres
DB_HOST: shlink-db
DB_PORT: "5432"
DB_NAME: shlink
DB_USER: shlink
DB_PASSWORD: change-this-strong-password
# Initial API key — use this to authenticate API requests
INITIAL_API_KEY: your-api-key-change-this
# Timezone for visit tracking
TIMEZONE: UTC
# GeoLite2 license key for IP geolocation (free, get from maxmind.com)
# GEOLITE_LICENSE_KEY: your-key-here
depends_on:
shlink-db:
condition: service_healthy
networks:
- shlink-net
shlink-db:
image: postgres:16.6-alpine
restart: unless-stopped
environment:
POSTGRES_DB: shlink
POSTGRES_USER: shlink
POSTGRES_PASSWORD: change-this-strong-password
volumes:
- shlink-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U shlink"]
interval: 10s
timeout: 5s
retries: 5
networks:
- shlink-net
shlink-web-client:
image: shlinkio/shlink-web-client:4.3.0
restart: unless-stopped
ports:
- "8081:8080"
# Configure via the web client UI on first load — add your Shlink
# server URL (http://shlink:8080 internally, or your public URL)
# and API key
networks:
- shlink-net
volumes:
shlink-db-data:
networks:
shlink-net:
Start the stack:
docker compose up -d
Access the Shlink Web Client at http://your-server:8081. Add a new server with your Shlink instance URL and the API key you set in INITIAL_API_KEY. You can also manage everything via the REST API:
# Create a short URL
curl -X POST http://localhost:8080/rest/v3/short-urls \
-H "X-Api-Key: your-api-key-change-this" \
-H "Content-Type: application/json" \
-d '{"longUrl": "https://example.com/very/long/url"}'
Docker Compose: YOURLS
This configuration runs YOURLS with MySQL. The admin panel is built in — no separate UI container needed.
Create a docker-compose.yml:
services:
yourls:
image: yourls:1.10.3
restart: unless-stopped
ports:
- "8080:80"
environment:
# Database connection
YOURLS_DB_HOST: yourls-db
YOURLS_DB_USER: yourls
YOURLS_DB_PASS: change-this-strong-password
YOURLS_DB_NAME: yourls
# Your short domain (with protocol)
YOURLS_SITE: https://links.example.com
# Admin credentials — change these
YOURLS_USER: admin
YOURLS_PASS: change-this-admin-password
volumes:
- yourls-plugins:/var/www/html/user/plugins
- yourls-pages:/var/www/html/user/pages
depends_on:
yourls-db:
condition: service_healthy
networks:
- yourls-net
yourls-db:
image: mysql:8.0.40
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: change-this-root-password
MYSQL_DATABASE: yourls
MYSQL_USER: yourls
MYSQL_PASSWORD: change-this-strong-password
volumes:
- yourls-db-data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
networks:
- yourls-net
volumes:
yourls-db-data:
yourls-plugins:
yourls-pages:
networks:
yourls-net:
Start the stack:
docker compose up -d
Access the admin panel at http://your-server:8080/admin. Log in with the YOURLS_USER and YOURLS_PASS credentials you set. The admin UI lets you create short URLs, view statistics, and manage plugins immediately.
Installation Complexity
YOURLS is easier to get running. One container plus MySQL, open the admin panel, done. The built-in web UI means you’re productive in under five minutes.
Shlink requires one extra step — setting up the web client container or learning the API. The API-first design means there’s no admin panel unless you deploy shlink-web-client alongside it. That said, once configured, Shlink is more powerful for day-to-day use if you’re comfortable with APIs or the web client.
Both are straightforward Docker deployments. Neither will give you trouble.
Performance and Resource Usage
Shlink has a clear architectural advantage. Running on Swoole or RoadRunner, it handles concurrent requests asynchronously — the PHP process stays resident in memory instead of spinning up per-request. Under heavy traffic (thousands of redirects per minute), Shlink maintains consistent response times.
YOURLS uses the traditional PHP-FPM model. Each request spawns a PHP process, connects to MySQL, resolves the redirect, and exits. This works fine for personal use and small teams. Under heavy load, you’ll need to tune PHP-FPM worker counts and MySQL connection pools.
| Resource | Shlink + PostgreSQL | YOURLS + MySQL |
|---|---|---|
| RAM (idle) | ~80 MB | ~60 MB |
| RAM (under load) | ~150 MB | ~200 MB (PHP-FPM workers) |
| CPU | Low | Low |
| Disk | Minimal (database only) | Minimal (database only) |
| Redirect latency | ~5-10 ms | ~15-30 ms |
For a personal URL shortener handling a few hundred clicks per day, neither will break a sweat. If you’re shortening URLs for a newsletter with 50,000 subscribers who all click at once, Shlink’s async runtime handles the spike better.
Community and Support
YOURLS has the larger community by raw numbers. Over 10,000 GitHub stars, 200+ plugins, active forums, and 15+ years of Stack Overflow answers. If you hit a problem, someone has solved it before.
Shlink has a smaller but growing community (~3,200 GitHub stars). Development is active — Alejandro Celaya ships regular releases with clear changelogs. Documentation is excellent and thorough. The API-first design means less surface area for community plugins, but the core functionality is more complete out of the box.
Both projects are actively maintained in 2026. Neither is at risk of abandonment.
Use Cases
Choose Shlink If…
- You want to create short URLs from scripts, CI/CD pipelines, or other applications
- You need multi-domain support (one instance, multiple short domains)
- You want detailed analytics with bot detection and geolocation
- You prefer PostgreSQL or SQLite over MySQL
- You’re building URL shortening into a larger automated workflow
- You expect high traffic and need async request handling
- You want to import existing short URLs from Bitly or another service
Choose YOURLS If…
- You want a working admin panel out of the box with zero extra setup
- You rely on plugins to customize behavior (custom keyword filtering, social sharing, branded previews)
- You’re already running a MySQL server and want to reuse it
- You prefer a battle-tested project with a decade of community support
- Your use case is simple: shorten URLs, share them, check stats
- You’re not comfortable with REST APIs and prefer a point-and-click interface
Final Verdict
Shlink is the better URL shortener for most self-hosters in 2026. Its API-first architecture, multi-database support, built-in bot detection, multi-domain handling, and async runtime make it the more capable and future-proof choice. The Shlink Web Client gives you a clean management UI when you need one, and the REST API gives you full programmatic control when you don’t.
YOURLS is not a bad choice — it’s simpler to set up, has an enormous plugin library, and its built-in admin panel is genuinely convenient. If you just need to shorten a few links per week and want the least friction possible, YOURLS gets the job done. But for anything beyond basic use, Shlink is the stronger foundation.
Pick Shlink unless you have a specific YOURLS plugin you can’t live without.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments