For developers coming from the web front-end world without a computer science background, dealing with system configurations can feel tedious, especially at the beginning.
I remember hating this part, deeply, until I had the ✨ brilliant ✨ idea of installing a tool I already had, blindly trusting that everything would somehow "just work" and the system would automatically swap versions.
Spoiler: it didn’t 🙂 I spent hours going crazy trying to fix the mess with my enviromental variables.
Eventually, things started working again... but honestly, I had no idea why they did. I hadn’t understood what I had broken, nor what I had accidentally fixed.
After that painful experience, I made myself a promise: keep an eye on the $PATH.
Months later, one random day, I ran echo $PATH just to check... and I gasped: the story was about to repeat itself:

But this time, I caught it early enough to avoid another descent into madness.
That’s when I decided: it was time for me to control my machine, not the other way around!
Fist, A Basic Question: What Is $PATH?
$PATH is an environment variable
lists directories where the system looks for executable programs
Why do we need it?
For you, so can easily run tools from the CLI (git, node, ruby, etc.)
For the shell, so it can find the corresponding executable when you type a command
Without $PATH, your terminal wouldn't know where to find git, node, ruby, brew, or anything else
How The Shell Searches For Commands
The shell reads your $PATH
Starts from the first directory
Checks if a file matching your command name exists and is executable
If found, it executes it immediately
If not, it moves to the next directory
Here's a visual sketch of the process:

If no match is found, you get the infamous error: zsh: command not found: brew
Yes: the lookup for the executable is a simple linear search, and that's why:
the order in which the directories appear in your $PATH is important
And fun fact: shells like zsh cache found commands in a hash table for faster reuse.
So, basically once it has found the executable in your $PATH it won't perfom the search all over again once you type the command. It will look into its hash table first.
Now, going back to the (beautiful) $PATH I showed you at the beginning, you can see two times Postgresql version 15:

But what if eventually I would have wanted to install and use Postgresql version 16?
Then, most likely, if I wouldn't have paid attention, I would ended up having in my path:

...which brings me to the issue I described initially.
No thanks, I like to live an happy life. That means: time to roll up my sleeves and fix the problem for good.
How To Clean Repeated Entries In $PATH
The strategy that worked for me was consisting of 6 easy steps:
1 - manually remove from .zshrc file any $PATH declaration for the old verisons of the tools
2 - remove any other explicit $PATH declaration for the tools that were not necessary (for some tools the $PATH is updated in the background during the installation)
3 - add at very top of the .zshrc file the command: typeset -U path and save

5 - close all the istances of the terminal (if you want to be extra-clean, go for a full reboot of the system)
6 - reopen the terminal and run source ~/.zshrc
7 - and finally run echo $PATH | tr ':' '\n’
Result: clean $PATH, as it was always meant to be:

Veri nais. My mental health was saved and grateful.
Now, The Nerdy Stuff: Understanding macOS System Directories (briefly)
The main issue was fixed, but I still had a little pebble in my shoe, something small but important before I could really say, “I fully control my $PATH.”
I won't go deep into this (maybe will be covered in another article), but here's a taste:
/bin and /sbin contain essential binaries needed for macOS to boot
/usr/bin and /usr/sbin have everyday system tools you use without even realizing
/usr/local/bin and /opt/homebrew/bin are where your custom-installed stuff usually ends up
If /bin or /sbin vanish, your Mac won’t even boot.
If /usr/bin or /usr/sbin disappear, macOS will boot... but good luck using it normally.
TL;DR
$PATH is an environment variable listing where executables live
The shell searches the $PATH linearly to find commands
The first match wins
Duplicates don't hurt performance badly, but keeping $PATH clean avoids weird version conflicts.
System directories (/bin, /sbin, /usr/sbin) are there so macOS and your terminal work properly; leave them alone!