I’ve always found traditional budgeting advice to be slightly broken. It usually sounds something like this: “You spent too much on dining out last month. Stop doing that.”
That’s like telling a piece of software that crashed, “Hey, stop crashing.” It’s not helpful. It addresses the output, not the logic that produced it.
In my quest to treat my life like a system that can be engineered, I’ve started looking at my finances through a different lens. I don’t just look at the spreadsheet (the logs); I look at the algorithm.
Specifically, I’ve been mapping my spending habits using a concept from computer science called a Finite State Machine (FSM).
If you’re not a developer, don’t worry. A Finite State Machine is just a fancy way of modeling a system that can exist in one of several specific “states” at any given time. It transitions from one state to another based on “inputs” (triggers).
Your toaster is a state machine.
- State 1: Off.
- Input: You push the lever down.
- Transition: It moves to State 2: Toasting.
- Input: Time runs out.
- Transition: It pops up and returns to State 1: Off.
Simple, right?
But here is the insight: You are also a state machine. And your wallet is the output device.
If you can map out the states you go through before you buy something, you can find the bugs in your code. You can find the infinite loops that are draining your bank account.
Let’s refactor your spending logic.
Phase 1: Mapping the “Spaghetti Code” of Impulse Buying
Getty Images
Explore
Most of us think spending is a binary action: we see something, we buy it. But when you slow it down, there is always a sequence of states.
For a long time, my “Impulse Buy” state machine looked like this:
- State: IDLE. (I am bored/tired/anxious).
- Input: I open a social media app.
- Transition -> State: BROWSING. (Passive consumption).
- Input: I see a targeted ad for a “productivity gadget.”
- Transition -> State: FANTASY. (I imagine how this gadget will fix my entire life).
- Input: “One-click purchase” button.
- Transition -> State: TRANSACTION. (Money leaves).
- Transition -> State: REGRET. (3 days later).
This is what developers call “spaghetti code.” It’s messy, reactive, and prone to errors. The transition from Browsing to Transaction happens too fast. There are no error checks. There is no “Guard Clause.”
When I looked at my credit card bill, I wasn’t seeing “items I bought.” I was seeing instances where my internal code executed a bad loop.
Phase 2: Identifying the Inputs (Triggers)
In an FSM, the system sits in a state until an Input triggers a change.
If you want to debug your finances, you have to identify the inputs.
- Internal Inputs: Boredom, hunger, insecurity, the “dopamine dip” at 3:00 PM.
- External Inputs: Push notifications, email newsletters, sale banners, a friend showing off their new car.
I realized that 80% of my unnecessary spending was triggered by a single specific input: Email Newsletters.
I would be in the IDLE state. I would receive an input (an email from a brand saying “Flash Sale”). My system would immediately transition to BROWSING.
I didn’t need the item. I wasn’t looking for the item. The input forced a state change.
The Fix: I unsubscribed from every single retail newsletter. I removed the input. Now, my system stays in IDLE (or hopefully, CREATING) because that specific trigger line of code has been deleted.
Phase 3: Writing a “Guard Clause”
In programming, a “Guard Clause” is a check that runs at the beginning of a function. If the conditions aren’t met, the function stops immediately. It prevents the code from running unnecessarily.
We need to inject a Guard Clause between the FANTASY state and the TRANSACTION state.
My personal Guard Clause is the 72-Hour Waiting Buffer.
Now, my State Machine looks like this:
- State: DESIRE. (I want the thing).
- Input: Attempt to buy.
- Guard Clause: Is this a recurring utility? No. Is this under $20? No. -> WAIT.
- Transition -> State: HOLDING PATTERN.
I write the item down in a “Wishlist” note (my holding buffer).
The HOLDING PATTERN is a valid state. I am allowed to want it. I just can’t transition to TRANSACTION yet.
Here is the magic: The HOLDING PATTERN state has a decay function. After 72 hours, the emotional “input” (the dopamine rush of the new shiny thing) usually fades.
90% of the time, the next transition isn’t to TRANSACTION. It’s to DELETE. The system resets to IDLE without spending a dime.
Phase 4: The “Garbage Collection” State
In languages like Java or Python, there is a process called “Garbage Collection.” The system automatically looks for memory that is being used by objects that are no longer needed and clears it out to free up resources.
We hold onto physical items (and subscriptions) long after they have stopped providing value. We stay in the OWNERSHIP state out of inertia.
I run a manual Garbage Collection script on my finances once a month.
- I look at every subscription.
- I ask: Does this object still point to a valid goal in my life?
- If
Value == Null, terminate process.
This sounds cold, but it’s actually liberating. It frees up “RAM” (cash and mental energy) for the things that are actually running the current version of my life.
Debugging the “Sunk Cost” Loop
The most dangerous bug in the human mind is the Sunk Cost Fallacy. In our State Machine, it looks like an infinite loop.
- State: OWNING A BOAT (or an expensive hobby).
- Input: It costs money to maintain.
- Logic: “But I already spent so much on it, I can’t sell it now.”
- Transition: Return to State: OWNING A BOAT.
This loop drains resources indefinitely.
A well-architected system recognizes when a process has “hung” (stopped working) and kills it.
If you have a hobby, a subscription, or even a car that is draining more resources than the value it provides, your code is stuck. You need to force a hard reset. You need to write a transition that says: If Output < Input for 3 months -> SELL.
Summary: You Are The Architect
The reason this matters—the “why” behind this geeky metaphor—is that financial freedom is a system reliability issue.
If your system is fragile (prone to crashing whenever a sale happens), you will never build enough capacity for the big things. You’ll always be patching bugs.
By mapping out your purchasing loops, you stop shaming yourself for “being bad with money” and start optimizing your logic.
- Identify the triggers (Inputs).
- Build better buffers (Guard Clauses).
- Clean up the waste (Garbage Collection).
Your life is the project. Money is just the resource allocation. Write cleaner code.