High-Yield Savings Account Tracking: Recording Interest Income in Beancount

Help! My Interest Income Tracking Is a Mess

Hey everyone, DevOps engineer here who recently moved her emergency fund into a high-yield savings account. With rates up to 4-5% APY in February 2026, I am actually earning meaningful interest for the first time in my life. The problem? I have no idea if I am recording it correctly in Beancount.

My Current Situation

I opened a Marcus by Goldman Sachs HYSA in November 2025 and deposited $12,000 (my starter emergency fund — working toward 4 months). At 4.10% APY, I am earning roughly $41/month in interest. Not life-changing, but over a year that is nearly $500 that I want to track properly.

Here is what I have been doing so far:

2025-11-01 open Assets:Savings:Marcus           USD
2025-11-01 open Income:Interest                 USD

; Initial deposit
2025-11-15 * "Transfer" "Open Marcus HYSA with emergency fund"
  Assets:Savings:Marcus      12,000.00 USD
  Assets:Checking:BofA      -12,000.00 USD

; December interest
2025-12-31 * "Goldman Sachs" "Monthly interest"
  Assets:Savings:Marcus         40.10 USD
  Income:Interest              -40.10 USD

; January interest
2026-01-31 * "Goldman Sachs" "Monthly interest"
  Assets:Savings:Marcus         41.24 USD
  Income:Interest              -41.24 USD

My Questions

1. Should I break out the income account more granularly?

Right now I just have Income:Interest but I also have a regular savings account at BofA that earns 0.01% (laugh all you want). Should I create:

  • Income:Interest:Marcus
  • Income:Interest:BofA

Or is Income:Interest:HYSA and Income:Interest:Regular a better split? What do experienced Beancount users do?

2. When exactly should I record the interest?

Marcus credits interest on the last day of each month. But the statement does not arrive until the 3rd or 4th of the following month. Do you record on the date the interest is credited (Dec 31) or the date you actually see it on the statement (Jan 3)?

3. Balance assertions — how often?

I have been doing monthly balance assertions after recording interest:

2026-01-31 balance Assets:Savings:Marcus  12,081.34 USD

Is this overkill? Some people seem to only do balance assertions quarterly.

4. What about the tax implications?

I know I will get a 1099-INT at the end of the year, but should I be doing anything in Beancount to track the tax liability along the way? With $500/year in interest income, is it even worth worrying about?

5. Compound interest tracking

Since the January interest is calculated on the December balance (which includes December interest), the amount goes up each month. Is there a clean way to model or predict this in Beancount, or do I just record whatever the bank says?

What I Have Tried

I looked at the Beancount documentation and found some examples, but most deal with investment accounts and capital gains. Simple interest income from a savings account seems too basic for anyone to have written about in detail.

I also tried writing a simple importer for Marcus, but their CSV exports are not great. Currently doing manual entry which takes about 5 minutes per month.

Any guidance from the community would be hugely appreciated. I know these questions are probably basic for most of you, but I want to get the foundations right before my emergency fund grows further.

Thanks in advance!

Sarah, these are all great questions and your current setup is actually better than you think. Let me address each one:

1. Income account granularity

I recommend splitting by institution, not by account type. The reason is that when tax time comes, your 1099-INT is per institution. So this maps cleanly:

2025-11-01 open Income:Interest:GoldmanSachs   USD  ; Marcus HYSA
2025-11-01 open Income:Interest:BofA            USD  ; Regular savings

Then at tax time you can run:

bean-query main.beancount "
  SELECT account, sum(position) as total_interest
  WHERE account ~ 'Income:Interest'
  AND year = 2025
  GROUP BY account
"

This gives you numbers that should match your 1099-INT forms exactly.

2. Recording date

Always use the date the interest is credited to your account, not when you see the statement. For Marcus, that is typically the last day of the month. This matches accrual-basis accounting and is what the bank reports to the IRS. Your Dec 31 date is correct.

3. Balance assertions

Monthly is not overkill — it is best practice for actively used accounts. I do monthly assertions for every account that has regular activity. It catches errors early. Keep doing what you are doing.

4. Tax tracking

At $500/year, the tax impact is roughly $60-120 depending on your bracket. You do not need quarterly estimated tax payments for this amount (the threshold where you might face underpayment penalties is generally $1,000 in total tax owed). Just make sure the total matches your 1099-INT at year end.

5. Compound interest

Do not try to predict it — just record what the bank credits. Beancount is a record-keeping system, not a forecasting tool. The compounding takes care of itself as each month’s interest becomes part of the balance that earns next month’s interest.

Your setup is solid. Keep going!

Adding to Mike’s excellent answers with some tax-specific detail.

On Question 4 (tax implications):

Mike is correct that $500/year in interest likely will not trigger estimated tax payment requirements by itself. However, I want to add some nuance:

The IRS requires estimated quarterly tax payments if you expect to owe $1,000 or more in tax that is NOT covered by withholding. So if you have other sources of non-withheld income (freelance work, investment dividends, etc.), the interest income stacks on top of those. It is the cumulative amount that matters.

For tracking in Beancount, I recommend at minimum adding a year-end reconciliation entry that matches your 1099-INT:

; Year-end reconciliation against 1099-INT
2025-12-31 custom "tax-document" "1099-INT"
  institution: "Goldman Sachs"
  box-1-interest: 82.58 USD
  tax-year: 2025
  status: "received"

This custom directive does not affect your balances but creates a searchable record that you received the tax document and what it said. When preparing your tax return, you can query all your tax documents:

bean-query main.beancount "
  SELECT * FROM custom
  WHERE type = 'tax-document'
  AND meta('tax-year') = '2025'
"

One more thing: If you earn more than $10 in interest from any single institution in a calendar year, the bank is required to send you a 1099-INT by January 31 of the following year. With $12,000 in Marcus at 4.1%, you will absolutely receive one. Keep it for your records — the IRS gets a copy too, and they will match it against your return.

Also, a small correction to Mike’s response: the 1099-INT threshold is $10 for the bank’s obligation to send the form. But you are required to report ALL interest income regardless of whether you receive a 1099-INT. Even the pennies from your BofA account.

Sarah, one practical tip on the Marcus importer since I fought with this too.

Marcus lets you download transactions as CSV, but the format is inconsistent. What I ended up doing is writing a dead-simple Python importer that handles their specific quirks:

# marcus_importer.py - Minimal Marcus HYSA importer
from beancount.ingest import importer
from beancount.core import data, amount
from decimal import Decimal
import csv
import datetime

class MarcusImporter(importer.ImporterProtocol):
    def identify(self, file):
        return 'marcus' in file.name.lower()

    def extract(self, file, existing_entries=None):
        entries = []
        with open(file.name) as f:
            reader = csv.DictReader(f)
            for row in reader:
                if 'Interest' in row.get('Description', ''):
                    meta = data.new_metadata(file.name, 0)
                    txn = data.Transaction(
                        meta,
                        datetime.date.fromisoformat(row['Date']),
                        '*',
                        'Goldman Sachs',
                        'Marcus HYSA interest',
                        frozenset(), frozenset(),
                        [
                            data.Posting('Assets:Savings:Marcus',
                                amount.Amount(Decimal(row['Amount']), 'USD'),
                                None, None, None, None),
                            data.Posting('Income:Interest:GoldmanSachs',
                                None, None, None, None, None),
                        ])
                    entries.append(txn)
        return entries

This is bare-bones but it automates the interest recording. You can expand it to handle deposits and withdrawals too. Save yourself those 5 minutes per month and invest them in something more fun.

Also, regarding your rate comparison: I just checked and Fortune reports that top HYSAs are still offering up to 5.00% APY as of this week (February 2026). If your Marcus is at 4.10%, it might be worth shopping around. Varo Money is reportedly at 5.00% and some others are above 4.20%. Even a 0.5% difference on $12,000 is $60/year — not huge, but it adds up as your emergency fund grows.