All articles

Self-hosting vs SaaS for link data

An honest accounting of running your own redirect infrastructure: what it really costs, what it actually buys, and when the answer is obviously SaaS.

8 min readBy gecis.in engineering
  • infrastructure
  • privacy
  • operations

gecis.in runs on our own hardware in Germany. That is a deliberate choice and we think it is the right one for what we are building, but the version of this argument that circulates online — self-hosting is cheaper, more private, and only slightly more work — is not true, and pretending otherwise makes for bad decisions.

So here is the accounting, including the parts that are inconvenient for us.

What is actually on the line

A link shortener is an unusual thing to self-host, because the redirect sits on the critical path of someone else's campaign. If your blog is down for an hour, you lose an hour of readers. If your redirect is down for an hour, every short link in every email, every QR code on every poster, and every link in every Slack thread is broken for that hour — including links printed months ago that you cannot recall.

That asymmetry should dominate the decision. Availability is not one factor among several here; it is the factor.

Some arithmetic on what the nines mean per month:

AvailabilityDowntime per month
99%7h 18m
99.9%43m
99.95%22m
99.99%4m 23s

99.9% on one machine in one datacentre is achievable and unremarkable. 99.99% is a different discipline — redundant everything, no single-instance database, and an on-call rotation with more than one name in it. Be clear about which one you are actually offering before you promise it.

The cost side, itemised

Latency, and where you are not. A redirect that goes to a single origin in Germany costs one intercontinental round trip for anyone who is not in Europe. Frankfurt to Sydney is on the order of 250 ms round trip on a good path — before TLS, before the redirect, before the destination's own load. A global anycast edge answers from a nearby city instead, and the difference is a large multiple, not a percentage.

This is the cost that self-hosting advocates most often ignore, and it is the one your users feel on every single click.

Availability work you now own. Backups that have actually been restored, at least once, from the backup — not backups that exist. Certificate renewal that does not fall over on a holiday. Kernel and dependency patching. A Postgres upgrade path. Disk that does not fill up. Someone reachable at 3am.

Postgres maintenance. Ours is partitioned by month so that the 90-day raw-IP retention is a partition DROP rather than a mass DELETE. That is the right design and it is also a thing that must be operated: partitions have to be created ahead of time, and there is a specific trap where an index declared on the partitioned parent stays indisvalid = f until it has been attached to every leaf — at which point the constraint you thought you had is silently not being enforced. Our migration verification counts the leaves via pg_inherits rather than eyeballing the result, because we learned that the hard way on a different system.

The GeoIP database. MaxMind's GeoLite2 is free but not frictionless: since the end of 2019 it requires an account and a licence key, and the files need refreshing on a schedule or your city data quietly rots. Ours is optional by design — if the .mmdb is missing the app degrades to country-only from Cloudflare's header rather than failing — but "degraded" is still a thing someone has to notice.

IP and domain reputation. Covered at length in a separate post. A SaaS provider is carrying this for you, and it is a larger job than it looks.

Opportunity cost. Every hour spent on the above is an hour not spent on the product. For a small team this is usually the largest line item, and it never appears on the infrastructure invoice.

The benefit side, itemised

Data residency that is a fact, not a setting. The rows are in a database in a datacentre you can name, under one jurisdiction. For customers whose procurement asks about GDPR Chapter V transfers, "in Germany, on our hardware" is a much shorter conversation than a list of subprocessors and standard contractual clauses. This is the benefit that most often justifies the whole exercise commercially.

Raw rows and SQL. Every click is a row you can query. When a customer asks a question the dashboard does not answer, the answer is a SELECT away rather than an export limit, an API rate limit, or a feature request. For a product whose pitch is depth of analytics, having the raw data is not a nice-to-have — it is the product.

Retention you control. Ninety days for raw IPs, enforced by a partition drop. Not a toggle in someone's settings page whose implementation you cannot inspect.

Schema you control. Adding a column takes a migration. On a SaaS analytics product it takes a roadmap.

No per-click pricing. Click-based pricing turns your own success into a cost curve, and it makes the perverse choice — sampling, or not tracking a link — occasionally rational. Fixed infrastructure cost does not have that shape.

You can read the code. Including the parts that are wrong. Several things in this blog were found by reading our own implementation twice.

The honest middle ground

Here is the part that undercuts the purity of the argument, and we would rather say it ourselves.

gecis.in sits behind Cloudflare. We read CF-Connecting-IP for the client address and CF-IPCountry for the country, which means Cloudflare terminates TLS and sees every single click before we do. "Fully self-hosted" is therefore already an approximation, and anyone who tells you otherwise about their own setup is either running their own anycast network or has not thought about it.

  • The redirect is a latency- and availability-sensitive commodity. An anycast edge, DDoS absorption and a global TLS terminator are things you should buy.
  • The data — the click rows, the analytics, the retention policy, the raw IPs — is the part where residency and control matter. That stays ours.

Splitting on that seam gets you most of the edge network's benefits and most of self-hosting's. It is not ideologically clean. It is the configuration we would actually recommend.

The corollary is that "self-hosted" is not a binary. It is a set of independent decisions — where TLS terminates, where the redirect is served, where the rows live, who can query them — and the interesting answers are usually mixed.

When SaaS is obviously right

Not a rhetorical section. The answer is genuinely SaaS if:

  • Nobody on the team wants to be on call. This is a legitimate and common answer, and it beats a heroic setup with one person who is on holiday.
  • You need a global edge and cannot buy one convincingly. If your audience is worldwide and you are not comfortable running the Cloudflare-in-front split above, take the managed edge.
  • Link management is not your product. If you need short links for marketing, paying for them is straightforwardly the right call. The build-versus-buy line should sit at the edge of what you are actually selling.
  • You need features that are large products in themselves. Deep-linking into mobile apps, deliverability integrations, enterprise SSO and audit trails, per-seat permissions. Each of these is months of work.
  • Volume is low. Below some threshold the SaaS bill is smaller than one afternoon of your time per month, and there is no argument to have.

Conversely, self-host when the data is the reason you exist — when residency is contractual, when you need the raw rows, when retention is a promise you have to be able to demonstrate, or when per-click pricing makes the economics not work at your volume.

A checklist instead of a conclusion

Before choosing to self-host a redirect service, be able to answer all of these:

  1. What availability are you offering, in a number, and who is paged?
  2. When did you last restore from a backup? (Not "do you have backups".)
  3. Where does TLS terminate, and who sees the traffic before you do?
  4. What is the p95 redirect latency from your furthest significant market?
  5. Who watches for domain-reputation listings, and what is the takedown path when a customer's link goes bad?
  6. Which regulation is driving the residency requirement, and does it actually require what you think it does?
  7. What is the migration path off this, if the answer changes in two years?

If several of those have no owner, the honest read is that you are not self-hosting — you are deferring a set of operational problems until the first incident makes them urgent. That is a decision too, but it should be made knowingly.

We can answer all seven, which is the only reason we think our version of this is defensible.

Articles are published in English.

gecis.in Blog · RSS