Self-hosting a URL shortener used to be a weekend project. PHP plus MySQL plus a redirect controller and you had something resembling Bitly circa 2010. The category has not stood still; the modern open-source options are more capable than YOURLS, more demanding to operate than the weekend project, and still meaningfully behind a hosted product on the analytics surface. This post is the honest landscape — what each open-source option actually delivers, what you give up versus a hosted vendor, and where the maths flips back in favour of paying someone else to run the redirect tier.
The audience is engineering teams or technical operators considering whether to self-host. The bitly alternatives cornerstone covers the broader comparison; this post zooms into the open-source side specifically. The self-hosting Elido k3s playbook covers the case where you want to self-host Elido itself rather than a third-party alternative.
What you are signing up for#
A URL shortener looks deceptively small. A database, a redirect process, a dashboard for managing links. In production, the simple shape hides four operational surfaces:
The redirect tier. This is the hot path. Every short URL clicked anywhere on the internet eventually hits this code. It needs to be fast (sub-15ms p95 if you care about user experience), highly available (downtime here breaks every link you have ever shipped), and globally distributed if your users are not in one geography. The redirect p95 < 15ms post covers what fast actually means and how it is achieved.
The click analytics pipeline. Recording, storing, and querying click events. At volume this is a different system from the redirect tier — typically Kafka or Redpanda for ingestion, ClickHouse or BigQuery for storage, a separate API for queries. Most open-source shorteners skip this entirely and store clicks in the same relational database that holds the links, which works at small volume and falls over once you cross a few million clicks per month.
The dashboard. UI for creating, editing, organising, and analysing links. Where most open-source projects spend the bulk of their feature work, and where the gap to hosted products is the smallest — most open-source dashboards are decent.
The custom-domain machinery. TLS issuance, DNS validation, certificate renewal, on-demand cert provisioning when a new domain points at the cluster. This is where the operational cost compounds; running ACME at scale is genuinely hard.
A self-hosted setup means you operate all four surfaces. A hosted product means you operate none of them (in exchange for paying a vendor and accepting their data-residency posture). The question is which set of trade-offs lands cleaner for your situation.
The current open-source options#
Five projects worth considering, in approximate order of activity as of access 2026-05-22.
YOURLS#
The granddaddy. PHP, MySQL, single-server, plugin architecture. YOURLS has been around since 2009 and remains the most-deployed open-source shortener by a wide margin. Strengths: simple to install, runs anywhere PHP runs, plugin ecosystem is mature. Weaknesses: analytics are minimal (click count per link, geo IP via an external service), no built-in custom-domain support beyond running multiple instances, no API rate limiting, no concept of teams or roles.
YOURLS is a fine choice if you want a personal short-link tool with a single owner and modest traffic. It is the wrong choice if you have a team, custom domains for clients, or analytics that need to outlive the database. The Elido vs YOURLS post covers the feature gap in detail.
Shlink#
PHP again but more modern. Shlink ships with a REST API, multi-domain support, a separate web UI, and Mercure-based real-time updates. The analytics are more capable than YOURLS — geo per visit, device, time series — but stored in the same MySQL/Postgres database as the links. The Shlink team is responsive and the project has shipped consistent releases since 2019.
Shlink is a reasonable choice if you are willing to operate a PHP-FPM + MySQL/Postgres setup and you do not need the analytics to scale past a few million clicks per month. The single-process redirect tier becomes a bottleneck at higher volumes; horizontal scaling is possible but requires you to front it with a load balancer and shared cache.
Polr#
Lightweight PHP. Polr was popular around 2017-2019 and the project is largely dormant now, though forks exist. Functionally similar to YOURLS but with a cleaner API. If you are starting today, the lack of recent maintenance is a meaningful concern — security patches do not arrive on a schedule.
Kutt#
Node.js, Postgres, Redis. Kutt is the most-active "modern stack" shortener. Ships with a custom domain feature, password-protected links, expiration, and basic analytics. The analytics surface is more usable than YOURLS but still relational-database-backed.
Kutt's operational profile is heavier than YOURLS — Node + Postgres + Redis means three services to run rather than one — but the modern stack gives you better performance per dollar at moderate volumes. If your team is comfortable with Node, Kutt is the safest "we want a modern open-source shortener" choice today.
Dub-self-hosted#
Dub.co publishes a self-host version of their hosted product. Dub ships a Next.js + Postgres + Redis + Tinybird stack with a polished dashboard and decent analytics. The operational complexity is the highest of the five — Tinybird is a hosted ClickHouse service in the default deployment, and replacing it with self-hosted ClickHouse is a significant project.
Dub-self-hosted is the right choice if you have a team comfortable operating a modern web stack and want the look-and-feel of a current hosted product. It is the wrong choice if your operational budget is constrained or your team is not Next.js-fluent.
The vendor matrix#
A four-axis grade across analytics, operations, custom domains, and scaling headroom. Grades are coarse — A through D — based on what the project ships out of the box, not what is possible with custom work.
| Project | Analytics | Operations | Custom domains | Scaling | Stack |
|---|---|---|---|---|---|
| YOURLS | D | A | C (manual) | D | PHP + MySQL |
| Shlink | C | B | B | C | PHP + Postgres |
| Polr | D | B | C | D | PHP + MySQL |
| Kutt | C | C | B | C | Node + Postgres + Redis |
| Dub-self-hosted | B | D | A | B | Next.js + Postgres + Redis + Tinybird |
| Elido-self-hosted | A | C | A | A | Go + Postgres + Redis + ClickHouse + Redpanda |
Two patterns from the matrix. First, analytics improves with stack complexity — projects that store clicks in a relational database alongside links score lower than projects that ship a dedicated analytics pipeline. Second, custom domains are reasonably well-served by everything except YOURLS, because ACME automation has become commoditised.
The hidden cost: analytics that scale#
Click events accumulate faster than people expect. A single link with 100 clicks per day generates 36,500 clicks per year — manageable in any relational database. A single link with 100,000 clicks per day generates 36.5M clicks per year, and that is where MySQL or Postgres starts groaning. A small SaaS product with a thousand active links averaging 1,000 clicks per day each is a billion clicks per year, and at that point any relational store falls over without significant tuning.
The five open-source projects above (except Dub and Elido) store clicks in the same database as the links. The query patterns are also different from typical OLTP — "give me click counts per day for this link over the last 30 days" is a range scan with aggregation, the worst case for an OLTP-tuned database.
You can solve this. ClickHouse handles billion-event analytics workloads comfortably; the why ClickHouse post covers the reasoning. But adding ClickHouse to your stack means another service to operate, another backup pipeline, another monitoring surface. If your link volume is small (under 10M clicks per month) the relational-database approach is fine for years; if your volume is larger, the analytics tier becomes a project of its own.
The hidden cost: edge POPs and latency#
A single-server self-hosted shortener serves redirects from one geographic location. If your users are in three continents, the latency from the far side is 200-300ms — visible in user-experience terms.
The fixes:
- Anycast IPs in front of multiple POPs. Practical only if you have your own AS and BGP setup. Not realistic for most self-hosted deployments.
- DNS-based geo-routing. Cloudflare, Route53, or NS1 can route users to the nearest POP. Works but adds a DNS-lookup latency on top of the redirect.
- CDN in front. Cloudflare or Fastly in front of the redirect process. The CDN caches GET responses; redirects are cacheable but the cache invalidation logic when a link destination changes is non-trivial.
- One POP per region. Run the redirect process in Frankfurt, Ashburn, and Singapore, with a shared database or eventual consistency between them. This is the production path. It is also significantly more work than self-hosting in a single region.
The edge POPs vs DNS-only routing post covers the choice in detail. Most self-hosted deployments stop at one region because the multi-region work is a separate project.
When self-hosting makes sense#
Three scenarios:
Data sovereignty is non-negotiable. A regulated industry — health, finance, government — requires data to live on your infrastructure. The hosted product's posture (even an EU-resident one) is not sufficient because the data has to live inside your security boundary. Self-hosting is the correct answer here. The maintenance cost is the price of compliance.
The volume is small and you are technical. A team running its own short links for internal use, with under a million clicks per month, no custom domains for external customers, and a developer who can keep one Docker Compose stack alive. YOURLS or Shlink fits cleanly. The hosted product is overkill for this scope.
You are building a derivative product. If your short links are the front-end of a larger product you are building — say, an event ticketing platform where the short URL points to the ticket — self-hosting lets you couple the redirect tier with your business logic in ways the hosted vendor cannot match. Most of Dub's self-host adopters are in this category.
When self-hosting stops making sense#
Three scenarios on the other side:
You need decent analytics. Once your stakeholders ask "how do clicks break down by country over the last 90 days for these 50 campaigns?", relational-database storage breaks down. You either build the analytics pipeline (a multi-month project) or pay a hosted vendor that ships it out of the box.
You need custom domains for many customers. Running ACME for one domain is trivial. Running ACME for 10,000 customer-supplied domains, with revocation, renewal, and on-demand issuance, is a serious engineering surface. The custom domain TLS post covers the mechanism; building this in-house is a quarter of work, not an afternoon.
Your team's time is the bottleneck. A self-hosted shortener costs roughly 4-8 engineer-hours per month in steady state once it is set up, plus the time of every outage and every upgrade. At a developer hourly rate of $100, that is $400-800/month before accounting for the inevitable two-week outage-debugging session every quarter. A hosted vendor at $300-500/month starts to look cheap.
The break-even calculation is sensitive to two inputs: how much your team's time is worth and how often you hit operational issues. For a team running its own k3s cluster anyway, the marginal cost of adding a shortener is low. For a team that does not currently operate any infrastructure, hosting the shortener pulls in adjacent costs (monitoring, logging, backups) that compound the bill.
A pragmatic decision tree#
The decision in five questions:
- Are you required by regulation or policy to keep link data on infrastructure you control? If yes, self-host. Stop here.
- Is your click volume currently or expected to exceed 50M clicks per month within 24 months? If yes, plan for a dedicated analytics tier — which biases towards either Dub-self-hosted or Elido-self-hosted, or a hosted vendor with ClickHouse-backed analytics.
- Do you need custom domains for more than 10 customers? If yes, the ACME automation cost is meaningful — same projects as above, or hosted.
- Does your team currently operate other production services with on-call rotation? If no, the operational cost of self-hosting is higher than it appears.
- Are short links a strategic surface of your product (e.g. you are building an integration platform) or a supporting utility (e.g. internal team links)? Strategic-surface = self-host or hosted with deep integration; supporting utility = whichever is cheaper.
Most teams will land on hosted after running this tree. That is fine. Self-hosting is the right answer when the constraints are clear; it is the wrong default when they are not.
Related reading#
- Bitly alternatives — the actual feature gap — the broader hosted-vendor cornerstone.
- Self-hosting Elido on k3s — the playbook — the operational walkthrough for the Elido side.
- Elido vs YOURLS — the head-to-head against the most-deployed open-source option.
- Why ClickHouse for click analytics — the analytics-tier reasoning.
- Edge POPs vs DNS-only routing — the multi-region path.
- Product surface:
/solutions/developersand/pricing. - Architecture: edge-redirect docs.