Dependency pinning

July 25, 2025

Today I want to share a trick I stumbled upon. It won’t matter to most of you. If it does matter to you, it will probably save you a bunch of headaches!

First, some background.

Have you ever had to use an outdated dependency for $REASONS? If not, you can skip today’s email, unless you’re just curious.

One of my clients is still using MongoDB 3.2. MongoDB was EOLed more than a year before anyone had ever heard the term “COVID”. Yeah. It’s that old.

Some time shortly after MongoDB 3.2, they improved the wire protocol that MongoDB servers and clients use to communicate. And since MongoDB 3.2 is so very, very old, MongoDB client libraries dropped support for the old wire protocol.

This means we cannot use the latest MongoDB Go driver in our project. But every time I run go get -u ./... to update dependencies, which in general is a good idea, of course, I break our MongoDB integration. Unfortunately, Go’s dependency management system does not support pinning dependencies to specific versions.

What can be done?!

My old solution was to simply go get <package> for each dependency except the MongoDB driver. But that’s both tedious and error-prone.

But I stumbled upon a work around, and that’s what I want to share with you today.

While Go doesn’t allow version pinning, it does allow you to replace one dependency with another. And you can replace it with a very specific version of another… Which means that by using the replace directive in your go.mod file, you can effectively pin a dependency to a specific version. Here’s how I did it:

// Pin this version of the mongo driver, until we can upgrade to a newer version
// of the server.
replace go.mongodb.org/mongo-driver => go.mongodb.org/mongo-driver v1.10.4

Voilà!

I’ve effectively pinned the MongoDB driver to version v1.10.4. I can now run go get -u ./... with impunity!

Note, this does have limitations. It won’t work for library modules. That is to say, if you have a module, A with a replace directive, and module B depends on A, it will not pull in A’s replacement version. It will still do its own dependency resolution, and try to fetch the latest version of A’s dependencies.

But for my use case, where our Go module represents the final application, this works perfectly.


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Get daily content like this in your inbox!

Subscribe