Midterms 2026See who we think should earn your vote, based on our standardsThe guide →
WRITTEN IN PLAIN AMERICAN ENGLISH.
CLAY TRIBUNE.
Advertisement

Don’t Couple Your Go Code to GitHub — Use Your Own Domain Instead

A tale of Go code chained to GitHub, and the custom domain that sets it free.

By mitch·6 min read
A glowing Go symbol floats amid data streams, freed from its earthly chains.

Go developers have a problem that sounds ridiculous once you hear it: their code is stuck to GitHub. The solution, according to Iain Cambridge, is simple — use your own domain instead.

Cambridge runs a project called Boneclone, and he has spent years watching teams get tangled up in the way Go handles dependencies. The language lets you import code by its git hosting URL, which works great until you want to switch hosts. Then you have to rewrite every import line in every file across every project that depends on yours. It is a mess.

His post, titled “Don’t couple your Go code to GitHub,” explains why the standard approach is broken and offers a fix. The core idea is that Go’s import system should point to a name you control, not to a name controlled by a hosting provider.

Advertisement

The Problem With Git Hosting URLs

Go’s import system is clever. When you write import "github.com/thetrueares/boneclone" in your code, the compiler knows where to fetch the source. That is handy for finding bugs and distributing libraries without a central package manager. But it comes with a serious catch.

If you host your code at github.com/thetrueares/boneclone and later move it to gitlab.com/thetrueares/boneclone, your code stops working. Every client machine still reaches out to the old GitHub URL. The new version of the library never gets pulled down, and your software stays broken.

Cambridge describes a real-world case where this happened to a company using GitHub, GitLab, and Azure Devops at the same time. Changing the location of the code was so much work that the company decided to keep all three platforms running. They kept paying for three hosting services because moving one git URL broke everything.

“Which sounds completely nuts, but it’s something that is pretty much defacto in the Go community.”

That is the crux of the problem. The import system couples your code to a hosting provider, and the overhead of switching is so high that teams simply do not bother. They stay locked in.

The Case for Custom Domains

The fix is to break that coupling. Instead of importing from a git hosting URL, import from a domain you own. That way, you can move your code anywhere without touching a single import line.

Cambridge points to examples like go.iain.rocks, go.uber.org, and go.mongodb.org. These domains act as pointers. When you import go.iain.rocks/boneclone, the server behind that domain tells Go where to actually fetch the code. If you later move the code to GitLab, you just change where the domain points. The import line stays the same, and clients keep working.

The benefit is immediate. You can switch hosting providers without rewriting production code. You can retire an old server without breaking downstream consumers. You can even run multiple versions of your library side by side, serving different paths under the same domain.

For commercial teams, Cambridge argues, this is an easy way to avoid pointless coupling. He says every commercial software development team using Go should adopt custom domains for their internal libraries and packages.

How the Redirect Works

The trick works through HTTP redirects. When a Go client asks for go.iain.rocks/boneclone, the server responds with a redirect to the actual git hosting URL. If the request includes the ?go-get=1 parameter — meaning the Go tool itself is asking — the server serves an HTML file with metadata. Without that parameter, it redirects the human visitor to GitHub.

Here is how Cambridge’s Nginx config handles it:

“`nginx
server {
server_name go.iain.rocks;
root /var/www/go.iain.rocks;
index index.html;

location / {
    if ($args !~ go-get=1) {
        return 301 https://github.com/that-guy-iain$request_uri;
    }
    try_files $uri $uri/ =404;
}

listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/go.iain.rocks/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/go.iain.rocks/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

}

server {
listen 80;
listen [::]:80;
server_name go.iain.rocks;
return 301 https://$host$request_uri;
}
“`

The index.html file contains the metadata that Go needs to resolve the import. It includes a go-import meta tag pointing to the git hosting URL and a go-source tag with the repository’s tree and blob URLs.

“`html










“`

That setup means the Go tool can find your code anywhere, while humans browsing the domain see a friendly redirect to GitHub.

What Happens When You Move

The beauty of this system is that the move is invisible to everyone except you. You update the domain to point to the new hosting location. The HTML file changes to reflect the new URL. The Nginx config changes to point to the new location.

Clients that have already fetched your code keep using the cached version. New clients hit the redirect and get the updated location. There is no downtime, no rebuilds, no frantic search-and-replace across your codebase.

Cambridge’s own project, Boneclone, exists to make this easier. It handles skeleton code replication across multiple git hosting platforms at the same time, so teams can mirror their repositories without rewriting imports. His experience building it came from watching companies struggle with the exact problem he now solves.

Why This Matters Now

This is not a hypothetical concern. Cambridge saw a company pay for three hosting services because it could not bear the cost of changing one git URL. That is a real financial penalty for a design decision made years ago.

The problem is defacto in the Go community, he writes. Teams use git hosting URLs for imports without thinking about the consequences. They assume the import system is a feature, not a trap.

It is a trap. The coupling is real, and it costs money.

The Takeaway

The advice is straightforward. If you write Go code, consider using a custom domain for your imports. It costs almost nothing to set up, and it protects you from a costly mistake.

Cambridge’s post is a reminder that software design decisions have real-world consequences. A small convenience in one language feature can become a ball and chain for years. The fix, in this case, is simpler than the problem it solves.

The sequence of events in the story:

Event Detail
Problem identified Companies using GitHub, GitLab, and Azure Devops could not change git locations without rewriting imports
Solution proposed Use custom domains like go.iain.rocks instead of git hosting URLs
Example given go.iain.rocks/boneclone redirects to github.com/thetrueares/boneclone
Cost described A company paid for three hosting services because it could not change one URL
Tool built Cambridge created Boneclone to replicate skeleton code across multiple platforms

The takeaway is simple: do not couple your Go code to GitHub. Use your own domain instead. It is a small change, but it frees you from a trap.

Source material: “Don't couple your Go code to GitHub,” iain.rocks.

The Notebook

Get the Notebook.

The day's best stories and every fresh verdict, in plain English, in your inbox by seven. One email a day, no more.

We send one note to confirm. Every issue has a one-click way out.

Advertisement

Leave a Reply

Your email address will not be published. Required fields are marked *

As an Amazon Associate, Clay Tribune earns from qualifying purchases.