After three years of tracking expenses in Beancount, I realized I was doing it backwards. I was recording where money went after it was spent, then feeling bad about the results. Sound familiar?
Six months ago I switched to zero-based budgeting in Beancount and it completely changed my relationship with money. Every dollar gets a job before I spend it. Here’s exactly how I set it up.
What Zero-Based Budgeting Actually Means
The concept is simple: your income minus your allocated budget should equal zero. Not because you spend everything, but because every dollar is assigned a purpose - including savings, investments, and debt payments.
Income: $7,200
- Housing: $1,800
- Food: $600
- Transport: $400
- Insurance: $350
- Utilities: $200
- Investing: $2,500
- Emergency: $500
- Fun: $400
- Clothing: $150
- Subscriptions: $100
- Buffer: $200
= Remaining: $0
The key insight: saving and investing are budget categories, not leftovers.
The Account Structure
Here’s the Beancount structure I use. The trick is treating budget categories as virtual equity accounts that represent the purpose of your money:
; === INCOME ===
2025-01-01 open Income:Salary USD
2025-01-01 open Income:Side USD
; === REAL ACCOUNTS (where money physically lives) ===
2025-01-01 open Assets:Checking:Main USD
2025-01-01 open Assets:Savings:Emergency USD
2025-01-01 open Assets:Savings:Vacation USD
2025-01-01 open Assets:Investments:Brokerage USD
; === BUDGET CATEGORIES (where money is assigned) ===
; These track spending against allocated amounts
2025-01-01 open Expenses:Housing:Rent USD
2025-01-01 open Expenses:Housing:Utilities USD
2025-01-01 open Expenses:Food:Groceries USD
2025-01-01 open Expenses:Food:DiningOut USD
2025-01-01 open Expenses:Transport:Gas USD
2025-01-01 open Expenses:Transport:Insurance USD
2025-01-01 open Expenses:Personal:Clothing USD
2025-01-01 open Expenses:Personal:Fun USD
2025-01-01 open Expenses:Subscriptions USD
2025-01-01 open Expenses:Health:Insurance USD
2025-01-01 open Expenses:Health:Copays USD
Monthly Budget Allocation
At the start of each month, I record my budget as a note directive. This becomes my reference for the month:
2025-02-01 note Assets:Checking:Main "
=== FEBRUARY 2025 ZERO-BASED BUDGET ===
INCOME: $7,200 (salary) + $400 (side hustle) = $7,600
NEEDS (50%):
Housing:Rent $1,800
Housing:Utilities $200
Food:Groceries $500
Transport:Gas $200
Transport:Insurance $150
Health:Insurance $350
Subscriptions (essential) $60
NEEDS TOTAL: $3,260
WANTS (20%):
Food:DiningOut $200
Personal:Fun $400
Personal:Clothing $150
Subscriptions (entertainment) $40
Buffer (unexpected) $200
WANTS TOTAL: $990
SAVINGS & INVESTING (30%):
Investments:Brokerage $2,500
Savings:Emergency $500
Savings:Vacation $350
SAVINGS TOTAL: $3,350
TOTAL ALLOCATED: $7,600
REMAINING: $0
STATUS: Every dollar has a job.
"
Tracking Against Budget
As I spend during the month, each transaction falls into its budget category naturally through the expense accounts:
; Week 1 spending
2025-02-03 * "Safeway" "Weekly groceries"
Expenses:Food:Groceries 87.42 USD
Assets:Checking:Main -87.42 USD
2025-02-05 * "Shell" "Gas for commute"
Expenses:Transport:Gas 45.00 USD
Assets:Checking:Main -45.00 USD
2025-02-07 * "Steam" "Game purchase - budgeted fun money"
Expenses:Personal:Fun 29.99 USD
Assets:Checking:Main -29.99 USD
The Monthly Review Query
This is the query I run mid-month and end-of-month to see how I’m doing against budget:
; Budget vs Actual for current month
SELECT
account,
sum(position) as actual
WHERE
account ~ 'Expenses'
AND year = 2025
AND month = 2
GROUP BY account
ORDER BY sum(position) DESC
Then I compare against my note directive. If groceries are at $380 by mid-month against a $500 budget, I know I’m on track. If dining out is already at $180 against $200, I need to cool it for the rest of the month.
The “Pay Yourself First” Automation
The most important part of ZBB: investments and savings happen on the 1st, not the 31st.
; First of the month - non-negotiable
2025-02-01 * "Vanguard" "Monthly investment - automatic"
Assets:Investments:Brokerage 2,500.00 USD
Assets:Checking:Main -2,500.00 USD
2025-02-01 * "Transfer" "Emergency fund contribution"
Assets:Savings:Emergency 500.00 USD
Assets:Checking:Main -500.00 USD
2025-02-01 * "Transfer" "Vacation sinking fund"
Assets:Savings:Vacation 350.00 USD
Assets:Checking:Main -350.00 USD
By moving these first, I can only overspend what’s left. That’s the whole point.
What Changed for Me
Before ZBB, I was saving about 20% of my income and felt like I was doing okay. After implementing ZBB, I bumped to 33% without feeling more restricted. The difference was intentionality - I stopped spending $200/month on random Amazon purchases because I could see exactly what that money was supposed to be doing.
My FIRE projections moved up by nearly 3 years just from this shift. Not from earning more, but from being deliberate about where every dollar goes.
Questions for the Community
-
How do you handle variable income months? My side hustle income fluctuates $200-800/month. Right now I budget conservatively and treat anything extra as bonus investment money.
-
Envelope rollover: If I underspend on groceries by $50 this month, do you roll that into next month’s grocery budget or reallocate it? I’ve been sending surpluses to investments.
-
Anyone using fava-envelope? I’ve been doing this manually with notes and queries. Is the plugin worth setting up?
-
Joint budgets: For those budgeting with a partner, how do you structure the accounts? My partner isn’t a Beancount user (understatement) so I need to keep it simple enough to discuss.
The biggest thing ZBB taught me: you don’t need to earn more to save more. You need to decide where your money goes before it decides for you.