Go 4 min read

Your Go Module Path Outlives Your GitHub Repository

Key takeaways

  • A Go module path helps locate source code and identifies the dependency.
  • Moving a repository and changing its module path are separate operations.
  • A domain you control can keep imports stable when the hosting location changes.
  • That control comes with ongoing responsibility for domain renewal and repository discovery.

Publishing a Go library under your GitHub account is easy. Renaming your organization or moving to another hosting service gets more interesting once that address appears in other people’s code. The repository move may be the easy part.

The address becomes part of your interface

A Go module groups packages into a versioned unit. Its path appears in the module declaration in go.mod.

If that path is github.com/example/kit, someone using its parser package will typically write:

import "github.com/example/kit/parser"

Convenient enough. Readers can guess where the source lives, and the maintainer needs no separate domain or discovery service.

But the string also identifies the package. The hosting provider and account name have become part of the library’s **public identity**.

That gives a seemingly routine setup decision a long shelf life. You probably think carefully before naming an exported function. The module path deserves similar attention: other developers will build around it, and changing it can create work for them.

## Moving the repository doesn't rename the dependency

A GitHub path does not mean every build connects directly to GitHub. Depending on configuration and cache state, Go can retrieve dependencies through a module proxy or use a local copy.

Those mechanisms change how code reaches a machine. They do not change the dependency’s name.

If the old path still lets Go locate the source after a repository move, users may be able to keep their imports. They still depend on that old address and whatever service keeps it working. A repository redirect does not rewrite the module’s identity.

Changing the module path creates a different migration. Consumers need to update imports and dependency declarations. If both paths remain in the dependency graph, Go can treat packages under those paths as distinct, even when they originated from the same source code. That distinction can cause trouble when code passes exported types between packages.

An application developer can sometimes work around a sourcing problem with a **`replace` directive**. But a replacement in a library’s own `go.mod` does not automatically apply to projects that depend on it.

Fixing one application is manageable. Coordinating the same change across everyone using a library is a much larger job.

## Give the public name a home you control

A *vanity import path* lets you publish a module under your own domain:

```go
import "go.example.com/kit/parser"

The domain provides repository discovery information that Go’s tooling can read. The actual source can still live on GitHub.

This separates the name consumers use from the place you host the code. When the repository moves, you can update the discovery information while keeping the public module path intact.

There are conditions. The module declaration in the relocated repository must still match that path. Previous versions and their source must remain available so consumers can continue fetching the versions they need.

The benefit is **control over the name**. A hosting change can become something the maintainer handles centrally, without asking every consumer to edit code.

Timing matters, though. Moving an established library from a GitHub path to a vanity path still changes its public name. Choosing the domain before the first release makes this separation much easier to preserve.

## Owning the name means keeping it alive

A custom domain adds a small piece of infrastructure with a potentially long lifespan.

Someone must renew the registration, maintain DNS, and keep repository discovery working. Serving that information over HTTPS also means maintaining certificates.

If the domain expires or discovery stops working, environments fetching a dependency may fail. Proxies and caches can keep some builds running, but cached copies do not remove the maintenance obligation.

The tradeoff depends on the project:

- For an experimental tool, a GitHub path may be the simplest sensible choice.
- For a library that multiple teams or external products will use for years, controlling the public path becomes more valuable.
- For a project using its own domain, ownership needs to survive the original author’s departure.

As a library gains users, the cost of editing all those downstream projects can outweigh the cost of moving the repository itself. Choose a module path with those future consumers in mind. The name you type once may become a commitment they rely on for years.
Go GitHub Dependency Management Developer Ecosystem

Comments

    Loading comments...