CASE STUDY · Glink

We shut down glincker.com, stripped it to the one tool worth keeping, and rebuilt the backend in Go in a week without losing either of our two users.

Killing a three-process stack to ship a 7-character link shortener

Shipped: 2026-06-213 min read

PROBLEM

The problem

Glincker.com had 22 URLs in its sitemap and three tools that actually worked: a URL shortener, a profanity filter, and a markdown converter. Running it required three processes: a Spring Boot backend, a Python AI core, and a standalone React frontend. That is a lot of ops surface for a product with 2 users. On top of the complexity, the glincker brand and the glinr brand were competing for the same mindshare, and neither was winning. The honest read: we built glincker to learn the stack, not to grow a user base. It served that purpose. Keeping it alive was paying a maintenance tax on an identity we had already moved past.

APPROACH

Our approach

The first decision was whether to rebuild glincker.com or fold it into glinr.com. We chose to fold it. Rebuilding would have given us the same surface area in a new shell; folding let us cut aggressively. Of 22 sitemap URLs, three mapped to real tools. The rest were either placeholder pages or features that never shipped (Notes app, Link-in-Bio, a React UI library that existed only in the nav). We killed all of those outright.

For what remained, we picked the one tool with a clear home in the new product line: the URL shortener. It became Glink, a standalone product on glinr.com with owner-scoped CRUD, public redirect at /r/{code}, and 7-char base62 codes. Seven characters gives roughly 3.5 trillion combinations, which is well past the collision threshold for any realistic indie-scale usage. The profanity filter and markdown converter were single-screen utilities with no user data attached; they will get static tool pages later if there is demand, but they did not justify a migration sprint.

The backend rewrite took one week. We chose Go with chi for routing, sqlc for type-safe query generation against Postgres, goose for migrations, theauth-go v2.0.2 for auth, and OTel for tracing. This is the same stack that powers the rest of glinr-v2, so Glink does not introduce a new operational dependency. The old Spring Boot + Python core + React triple is gone; everything runs inside the monorepo now.

Migration plan: Glink first, then a Label maker and a QR generator (the two next candidates from the glincker feature list), then the small utility tools as static pages. We are not running all three services in parallel during the transition. Glincker.com is dark; 301 redirects point all known paths to glinr.com equivalents.

OUTCOME

What shipped and what we learned.

One stack instead of three. One brand instead of two. Both users migrated without a broken link or a lost session. The Spring Boot service, the Python core, and the standalone React frontend are all decommissioned. 301 redirects from glincker.com carry forward whatever SEO equity existed, which was modest but not zero.

3Legacy services killedSpring Boot, Python core, React FE
2 to 1Domains consolidatedglincker.com folded into glinr.com
3 of 22Functional tools shippedhonest cut from the sitemap
7 charsShort code length~3.5T combinations, low collision
1 weekBackend rewriteGo + sqlc + theauth-go
2 of 2Users migratedno signups lost

STACK

Technology stack

SCREENS

What it looks like.

Before: glincker.com dashboard with its three-process layout
Before: glincker.com dashboard, three services, 22 sitemap URLs.
After: glinr.com dashboard links section
After: glinr.com /dashboard/links, one service, one brand.
The new Go API showing the link domain handlers
The Go API: link domain with chi routing, sqlc queries, OTel spans.
301 redirect map from glincker.com to glinr.com paths
301 redirect map: every known glincker.com path points to glinr.com.

MORE WORK

Want to read more case studies?

Back to all work