Logo

dev-resources.site

for different kinds of informations.

Why pinning your dependency versions matters

Published at
11/12/2024
Categories
devops
kubernetes
bestpractices
webdev
Author
mlamina
Author
7 person written this
mlamina
open
Why pinning your dependency versions matters

500 error after crash

This is what my potential first customers saw when I launched the first email campaign for my latest project, all due to a crash that was not only unpredictable, but entirely avoidable. And it could happen to you too.

What happened

I have Postgres running as a Kubernetes deployment. In my values.yaml, I had set the following:

postgresql:
  image:
    tag: 15
Enter fullscreen mode Exit fullscreen mode

It worked perfectly for months until this morning, when I woke up to my database in a crashloop and my service completely unavailable. Why? It turns out K8s had to restart the PostgreSQL pod, which then loaded the latest 15.* version of the Docker image. Unfortunately for me, that image was buggy and sent my database down to into oblivion.

The impact

Half of the recipients of my email campaign opened the link and were greeted with a 500 error before I could identify and fix the issue. Apart from the fact that it is embarrassing, I probably lost a few potential customers due to this.

Why you should care and what you can do

Pin. Your. Dependencies.

The main thing here is that you don't want any devops or dependency management systems to have control over which versions are pulled into your system. No matter if it's Docker, Python, Maven, Gradle, NPM or whatever system you are using to manage your dependencies - Specify all versions down to the PATCH version.

Semantic versioning

If you don't know what semantic versioning is, I suggest you read up on it. In a nutshell, it is a standard/guideline for defining version numbers and how to increase them:

Given a version number MAJOR.MINOR.PATCH, increment the:

  1. MAJOR version when you make incompatible API changes
  2. MINOR version when you add functionality in a backward compatible manner
  3. PATCH version when you make backward compatible bug fixes Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

"Pinning" and why it matters

In my case, by setting the Docker image version to 15, I gave Kubernetes the freedom to download any minor or patch version of it - at any time, without warning. By "pinning" the version - in other words specifying MAJOR, MINOR and PATCH version explicitly - I regained control and the ability to update the image version on my own terms and test it thoroughly in my setup.

To summarize, this is bad:

postgresql:
  image:
    # Will potentially crash your application at any point
    tag: 15
Enter fullscreen mode Exit fullscreen mode

Stay safe by only allowing the latest PATCH version:

postgresql:
  image:
    # This will pull the latest 15.7.x patch version
    tag: 15.7
Enter fullscreen mode Exit fullscreen mode

Final thoughts

Even with 15 years of experience, rookie mistakes creep in. Not pinning your dependencies is an easy mistake to make, but can have dramatic consequences for your product and your company.

Ironically, the product I was about to launch could have actually helped me catch this issue before merging it into production ๐Ÿคฆโ€โ™‚๏ธ Check out PR Manager, where you can generate reviews for your code changes before merging them. It allows you to catch issues like the one in this post and lets you fix them with the click of a button.

bestpractices Article's
30 articles in total
Favicon
Why Test Driven Development
Favicon
Go Serialization Essentials: Struct Tags, Error Handling, and Real-World Use Cases
Favicon
Creating Safe Custom Types with Validation in Go
Favicon
Best Practices for Network Management in Docker ๐Ÿ‘ฉโ€๐Ÿ’ป
Favicon
Enforce DevOps best practices and eliminate production errors!
Favicon
The State of Cybersecurity Marketing: A Deep Dive Analysis
Favicon
Responsive Images: Best Practices in 2025
Favicon
Code Speaks for Itself: Mรฉtodos Bem Escritos Dispensam Comentรกrios
Favicon
Generate 6 or 8 digit alpha numeric code using best performance in C#
Favicon
How To Replace Exceptions with Result Pattern in .NET
Favicon
8 essentials for every JavaScript project
Favicon
Send a From Header When You Crawl
Favicon
The Open Source AI : Understanding the New Standard
Favicon
Best Practices for Using Azure ATP in Hybrid Environments
Favicon
TADOConnection: Proper Use of LoginPrompt
Favicon
Best Practices for Developing and Integrating REST APIs into Web Applications
Favicon
Mastering Cybersecurity: A Comprehensive Guide to Self-Learning
Favicon
Best Practices for Data Security in Big Data Projects
Favicon
Hopefully Helpful Notes, Best Practices, ...
Favicon
Best Practices for Using GROUP BY in MySQL for Converting Vertical Data to JSON
Favicon
Best Practices in Software Architecture for Scalable, Secure, and Maintainable Systems
Favicon
Cloud Computing Security Best Practices for Enterprises
Favicon
Why Interfaces Are Essential in .NET Development
Favicon
Git Tricks You Should Know: Aliases, Bisect, and Hooks for Better Workflow
Favicon
Why pinning your dependency versions matters
Favicon
Microservices Best Practices: Multi-Tenant microservices with Java SDK
Favicon
Apple Intelligence: Pioneering AI Privacy in the Tech Industry
Favicon
Improving JavaScript Performance: Techniques and Best Practices
Favicon
Test-Driven Development (TDD) in Ruby: A Step-by-Step Guide
Favicon
APIs and Security Best Practices: JavaScript and Python Examples

Featured ones: