What Is Envelope Budgeting?
For those unfamiliar, envelope budgeting is a system where you allocate your income into specific envelopes (categories) at the start of each month. You can only spend what is in each envelope. When the envelope is empty, you stop spending in that category or you explicitly move money from another envelope. It is one of the oldest and most effective budgeting methods, and it translates surprisingly well to double-entry accounting.
The challenge in Beancount is that it does not support virtual postings like Ledger or hledger do. But after four years of experimenting, I have found a clean approach using dedicated budget accounts.
The Account Structure
The key insight is to create a parallel set of budget accounts under a top-level Budget account:
2026-01-01 open Budget:Groceries
2026-01-01 open Budget:Restaurants
2026-01-01 open Budget:Utilities
2026-01-01 open Budget:Transportation
2026-01-01 open Budget:Entertainment
2026-01-01 open Budget:Clothing
2026-01-01 open Budget:Emergency
2026-01-01 open Budget:Savings
2026-01-01 open Budget:Available
Monthly Allocation
When you receive income, first record the actual income transaction as normal:
2026-02-01 * "Employer" "Monthly salary"
Assets:BankOfAmerica:Checking 5200.00 USD
Income:Salary -5200.00 USD
Then create an allocation transaction that distributes money into your envelopes:
2026-02-01 * "Budget Allocation" "February 2026 envelope funding"
Budget:Available -4200.00 USD
Budget:Groceries 600.00 USD
Budget:Restaurants 200.00 USD
Budget:Utilities 300.00 USD
Budget:Transportation 250.00 USD
Budget:Entertainment 150.00 USD
Budget:Clothing 100.00 USD
Budget:Emergency 200.00 USD
Budget:Savings 2400.00 USD
The remaining 1000 from the 5200 salary goes to taxes and benefits. The Budget:Available account acts as your unallocated funds pool.
Tracking Spending Against Envelopes
When you spend money, record the actual expense AND deduct from the corresponding envelope:
2026-02-05 * "Trader Joes" "Weekly groceries"
Expenses:Food:Groceries 87.34 USD
Assets:BankOfAmerica:Checking
2026-02-05 * "Budget Tracking" "Groceries envelope deduction"
Budget:Groceries -87.34 USD
Budget:Available 87.34 USD
Recording two transactions per purchase is tedious. That is where automation comes in. I use a Beancount plugin that automatically generates the budget tracking entry:
from beancount.core import data, amount
from beancount.core.number import ZERO
ENVELOPE_MAP = {
"Expenses:Food:Groceries": "Budget:Groceries",
"Expenses:Food:Restaurants": "Budget:Restaurants",
"Expenses:Housing:Utilities": "Budget:Utilities",
"Expenses:Transport": "Budget:Transportation",
"Expenses:Entertainment": "Budget:Entertainment",
"Expenses:Clothing": "Budget:Clothing",
}
def envelope_tracker(entries, options_map):
new_entries = list(entries)
for entry in entries:
if not isinstance(entry, data.Transaction):
continue
for posting in entry.postings:
budget_account = None
for expense_prefix, envelope in ENVELOPE_MAP.items():
if posting.account.startswith(expense_prefix):
budget_account = envelope
break
if budget_account and posting.units.number > ZERO:
meta = data.new_metadata("<envelope>", 0)
budget_txn = data.Transaction(
meta, entry.date, "*",
"Budget Tracking",
f"Auto-deduct from {budget_account}",
frozenset(), frozenset(),
[
data.Posting(budget_account,
amount.Amount(-posting.units.number,
posting.units.currency),
None, None, None, None),
data.Posting("Budget:Available",
amount.Amount(posting.units.number,
posting.units.currency),
None, None, None, None),
]
)
new_entries.append(budget_txn)
return new_entries, []
Checking Your Envelope Balances
Query your remaining budget at any time using bean-query:
bean-query main.beancount "SELECT account, sum(position) WHERE account ~ 'Budget' GROUP BY account"
The fava-envelope Alternative
There is also the fava-envelope extension by polarmutex on GitHub, which provides envelope budgeting through a Fava web interface with CSV-based budget definitions. The advantage is a nice visual dashboard without writing plugin code. The disadvantage is that your budget data lives outside your ledger file.
Handling Overspending and Rollovers
The beauty of this system is that overspending is immediately visible. If Budget:Groceries goes negative, you know you have overdrawn that envelope. You can reallocate:
2026-02-20 * "Budget Reallocation" "Move funds from entertainment to groceries"
Budget:Entertainment -50.00 USD
Budget:Groceries 50.00 USD
For rollovers, simply do not zero out the envelopes at month end. Whatever remains carries forward automatically. This is one area where plain-text accounting makes envelope budgeting easier than physical envelopes or most apps.
I have been running this system for 3 years and it has genuinely changed my relationship with spending. The forced intentionality of allocating every dollar is powerful.