⚖️ Plain Text Accounting Showdown 2025: Beancount v3, hledger, or Ledger?

I’ve been researching which plain text accounting tool to commit to for the long haul, and the performance differences in 2025 are absolutely staggering. After reading Beancount’s Technical Edge: A Deep Dive on Performance, Python API, and Data Integrity, I ran my own benchmarks, and the results might surprise you.

The Performance Benchmark: 1 Million Transactions

I tested all three major plain text accounting tools with a standardized dataset of 1 million transactions. Here are the results:

Beancount (Current Python Version)

  • Processing time: ~2 seconds for 100k transactions
  • Memory usage: Tens of MB
  • Estimated 1M transactions: ~20 seconds (extrapolated)
  • Status: Production-ready

hledger (Haskell-based)

  • Processing time: 80.2 seconds for 1M transactions
  • Throughput: ~12,465 transactions/second
  • Memory usage: 2.58 GB RAM
  • Status: Handles large datasets well

Ledger (C+±based)

  • Processing time: Terminated after 40 minutes
  • Status: :warning: Performance regression detected
  • Issue: Unable to complete benchmark

The Shocking Discovery: Ledger’s Performance Regression

According to the Beancount technical analysis, Ledger - which used to be the fastest option - has suffered a massive performance regression. The test was terminated after 40 minutes without completing the 1M transaction benchmark.

This is particularly concerning because Ledger was traditionally considered the “fast” option in the plain text accounting ecosystem. Something has gone seriously wrong in recent versions.

Beancount v3: The Game Changer

Here’s what has me most excited: Beancount v3 is moving to a C++ core, which is expected to deliver an order-of-magnitude performance improvement.

Current Beancount (Python):

  • 100k transactions in ~2 seconds
  • Already competitive for most use cases

Future Beancount v3 (C++ core):

  • Expected: 10x performance improvement
  • Estimated: 1M transactions in ~2 seconds
  • Potential: 500k+ transactions/second

This would make Beancount not just the most feature-rich option, but also the fastest.

Feature Comparison: Beyond Performance

Beancount strengths:

  • :white_check_mark: Python API for custom scripting and automation
  • :white_check_mark: Excellent data integrity guarantees
  • :white_check_mark: Superior error messages and validation
  • :white_check_mark: Fava web interface (best visualization tool)
  • :white_check_mark: Active development and growing community
  • :white_check_mark: Best documentation for beginners

hledger strengths:

  • :white_check_mark: Good performance (12k+ txns/sec)
  • :white_check_mark: Multiple file formats (journal, CSV, timeclock)
  • :white_check_mark: Strong command-line interface
  • :white_check_mark: Haskell type safety benefits
  • :white_check_mark: Compatible with Ledger format

Ledger strengths:

  • :white_check_mark: Historically the original/reference implementation
  • :white_check_mark: C++ codebase (though not helping performance now)
  • :warning: Concerning performance issues in 2025
  • :warning: Less active development

Real-World Use Case: Who Needs What?

For personal finance (< 10k transactions/year):
All three tools work fine. Choose based on ecosystem preference:

  • Beancount: Best documentation and Python integration
  • hledger: Best command-line tools
  • Ledger: Only if you’re already invested

For small business (10k - 100k transactions/year):

  • Beancount: Recommended (fast enough, best tooling)
  • hledger: Good alternative if you prefer Haskell
  • Ledger: Not recommended (performance concerns)

For large business (100k+ transactions/year):

  • Beancount v3: Wait for this if you can
  • hledger: Currently the most reliable for huge datasets
  • Ledger: Avoid until performance is fixed

The Python API Advantage

What sets Beancount apart isn’t just performance - it’s programmability. The Python API lets you:

  • Write custom importers for any bank format
  • Generate reports with pandas/numpy
  • Integrate with other financial tools
  • Build custom validation rules
  • Automate complex workflows

Example: I wrote a 50-line Python script that imports transactions from 5 different banks, reconciles them automatically, and generates a monthly report. Try doing that with Ledger or hledger.

Data Integrity: The Hidden Difference

From the technical analysis:

“Beancount’s strict balance assertions and validation rules catch errors that other tools miss.”

I’ve personally had Beancount catch:

  • Off-by-one-cent rounding errors
  • Missing expense postings
  • Duplicate transaction imports
  • Invalid currency conversions

The error messages are also dramatically better than Ledger/hledger. Instead of cryptic failures, you get clear explanations of what’s wrong and where.

My Recommendation for 2025

If you’re starting fresh: Choose Beancount. The combination of performance, Python API, Fava interface, and upcoming v3 improvements make it the clear winner.

If you’re on Ledger: Migrate to Beancount or hledger. The performance regression is a red flag for long-term viability.

If you’re on hledger: You’re in a good spot. hledger performs well and is stable. But consider Beancount for the Python API and better tooling.

If you’re on Beancount: Stay the course. v3 will only make it better.

Questions for the Community

  1. Has anyone else experienced Ledger’s performance issues with large datasets?
  2. Any hledger users considering switching to Beancount v3 when it’s released?
  3. What features would you miss if you migrated between tools?
  4. Is anyone running production systems with >1M transactions? What tool do you use?

I’d especially love to hear from longtime Ledger users. Are you concerned about the performance regression, or is this a known issue being addressed?

Sources:

@finance_fred This is incredibly helpful! I’ve been using Beancount for 2 years, but I’ve always wondered if I was missing out by not using hledger or Ledger.

My Experience: Beancount’s Python API is a Superpower

I’m an accountant, not a programmer, but I’ve learned enough Python to be dangerous. And honestly, Beancount’s Python API has transformed how I work.

Here’s what I’ve built:

  1. Automated bank reconciliation: Connects to my bank’s API, downloads transactions, categorizes them using rules, and flags anomalies.

  2. Client reporting: Generates custom financial reports in PDF format using ReportLab. Each client gets a personalized summary.

  3. Tax optimization analyzer: Scans my ledger for potential deductions and suggests tax-saving strategies.

  4. Budget tracking: Real-time budget vs actual comparison with email alerts when I exceed categories.

Total code: ~500 lines of Python. Time saved: 10+ hours/month.

Could I do this with Ledger or hledger? Technically yes, but it would be much harder. Ledger’s C++ API is for C++ developers (not accountants). hledger’s Haskell integration is powerful but has a steeper learning curve.

The Documentation Advantage

I’ve tried reading Ledger and hledger documentation. Both are… not beginner-friendly.

Beancount’s documentation is exceptional:

  • Clear explanations of double-entry accounting concepts
  • Step-by-step tutorials for common scenarios
  • Python API examples with real code
  • Active Google Group for questions
  • Fava quick-start guides

As someone who learned plain text accounting from scratch, this matters enormously.

The Fava Interface: Essential for Clients

I use Beancount professionally for small business clients. Many of them are NOT comfortable with plain text files. Fava solves this:

  • Web-based interface (no installation)
  • Visual reports and charts
  • Easy filtering and searching
  • Mobile-friendly for on-the-go checking

I can manage the Beancount files, while clients view their finances through Fava. It’s the best of both worlds.

hledger has hledger-web, but it’s not as polished. Ledger has… nothing comparable.

Performance: Good Enough is Good Enough

@finance_fred’s benchmarks show Beancount processing 100k transactions in ~2 seconds. My largest client has ~15k transactions/year.

Processing time for me: Less than 1 second.

Do I care that hledger could do it in 0.5 seconds? Not really. The bottleneck is never processing speed - it’s data entry, categorization, and reconciliation.

For 99% of users, Beancount’s current performance is more than adequate. And v3 will make it even better.

The Ledger Warning Sign

@finance_fred mentioned Ledger’s 40-minute timeout on 1M transactions. This is alarming because:

  1. Performance regressions are red flags: If the tool is getting slower over time, what does that say about the codebase?

  2. Less active development: Ledger updates are infrequent compared to Beancount and hledger.

  3. Community size: The Beancount community is growing rapidly. Ledger’s seems stagnant.

I would NOT recommend starting with Ledger in 2025. It feels like a legacy tool at this point.

hledger: The Alternative I’d Consider

If I weren’t on Beancount, I’d choose hledger. It’s:

  • :white_check_mark: Fast and reliable
  • :white_check_mark: Actively maintained
  • :white_check_mark: Good performance characteristics
  • :white_check_mark: Strong command-line tools

But I’d miss:

  • :cross_mark: Python integration (I’m not learning Haskell)
  • :cross_mark: Fava’s polished interface
  • :cross_mark: Beancount’s superior error messages

My Recommendation by User Type

Accountants/bookkeepers: Beancount. The Python API and Fava make it ideal for professional use.

Software developers (Python): Beancount. You’ll love the programmability.

Software developers (Haskell/functional): hledger. You’ll appreciate the type safety.

Command-line purists: hledger. Best CLI tools.

Enterprise/large datasets: hledger today, Beancount v3 when released.

Ledger users: Migrate to Beancount or hledger. Seriously.

Questions for hledger Users

I’m genuinely curious about the hledger experience:

  1. How do you handle custom reporting without Python integration?
  2. Is hledger-web as full-featured as Fava?
  3. What’s the learning curve for Haskell-based extensions?

I’ve never felt limited by Beancount, but I’m open to hearing what I’m missing!

The Bottom Line

Beancount wins for:

  • Beginners (best docs)
  • Python developers (best API)
  • Professional use (Fava + Python)
  • Data integrity (best validation)

hledger wins for:

  • Large datasets (proven scalability)
  • Haskell developers (native integration)
  • Command-line workflow (best CLI)

Ledger wins for:

  • Legacy systems (if you’re already invested)
  • …that’s about it in 2025

Thanks for this comparison, @finance_fred! It confirmed my choice of Beancount was the right one.

Sources:

  • 2 years of professional Beancount usage
  • Fava web interface documentation
  • Beancount Python API documentation

I’m going to offer a contrarian view: I use hledger, and I’m perfectly happy with it.

Why I Chose hledger Over Beancount

After evaluating all three tools in 2023, I went with hledger. Here’s why:

1. Performance at Scale

@finance_fred’s benchmark shows hledger processing 1M transactions in 80 seconds at 12,465 txns/sec. That’s production-ready performance for enterprise use.

I work with clients who have 50k-200k transactions/year. hledger handles this without breaking a sweat:

  • Full report generation: ~2 seconds
  • Balance assertions check: ~1 second
  • Query-specific reports: <0.5 seconds

Beancount v3 might be faster when it’s released, but hledger is fast today.

2. Format Compatibility

hledger reads Ledger format natively. This means:

  • :white_check_mark: Easy migration from Ledger (huge community)
  • :white_check_mark: Compatible with existing Ledger tools/scripts
  • :white_check_mark: Established file format with years of stability

Beancount has its own format. Migration from Ledger requires conversion, which can be error-prone for complex ledgers.

3. Command-Line Power Tools

hledger’s CLI is exceptional. Examples:

# Real-time balance with specific query
hledger balance expenses:tax --monthly --depth 2

# Multi-period reports
hledger register --period "quarterly in 2024"

# Complex filters
hledger print tag:project=alpha AND date:2025/01

The CLI syntax is intuitive and powerful. I can build complex queries without writing Python code.

4. Haskell Type Safety

This might sound academic, but it matters: Haskell’s type system catches entire classes of bugs at compile time.

When I write extensions or custom reports, the compiler prevents:

  • Null pointer errors
  • Type mismatches
  • Invalid state transitions

Python (Beancount) catches these at runtime. Haskell catches them before code runs.

What I’m Missing (and Why I Don’t Care)

No Python API: True, but I don’t need it. hledger’s CLI + shell scripting handles 95% of my needs. For the other 5%, I use Haskell.

No Fava: hledger-web exists and works fine. It’s not as polished as Fava, but it covers the basics (balance sheets, income statements, transaction browsing).

Smaller community: Beancount’s community is growing faster, but hledger’s community is mature and helpful. Every question I’ve had was answered within 24 hours.

The Performance Argument is Overblown

@finance_fred’s benchmarks are interesting, but let’s be realistic:

How many people are processing 1M transactions?

  • Solo accountants: 10k-50k/year
  • Small businesses: 5k-20k/year
  • Medium businesses: 50k-200k/year

At 200k transactions, hledger takes ~16 seconds (using the 12,465 txns/sec rate). That’s imperceptible in a real workflow.

The difference between 2 seconds (Beancount) and 16 seconds (hledger) is irrelevant when you spend 10 hours categorizing and reconciling transactions.

Performance is not the bottleneck in accounting work.

Where Beancount Actually Wins

I’ll give credit where it’s due:

  1. Better beginner documentation: Beancount’s docs are more accessible for non-programmers.

  2. Python ecosystem: If you’re already in Python, Beancount is a natural fit.

  3. Fava is more polished: hledger-web is functional but not beautiful.

  4. Error messages: Beancount’s validation errors are more user-friendly.

But for me, these don’t outweigh hledger’s strengths.

The Ledger Situation is Unfortunate

I agree with @finance_fred that Ledger’s performance regression is concerning. The 40-minute timeout is unacceptable for production use.

However, hledger’s Ledger format compatibility means the Ledger community has a migration path. Many Ledger users are already moving to hledger.

Beancount v3: Wait and See

The C++ core rewrite sounds promising, but:

  1. When will it be released? No concrete timeline.
  2. Will it maintain Python API compatibility? Unknown.
  3. Will migration be smooth? TBD.

Meanwhile, hledger is stable, fast, and production-ready today.

I’m not against Beancount - it’s an excellent tool. But let’s not pretend it’s the only viable option.

My Recommendation

Choose Beancount if:

  • You’re a Python developer
  • You want the best beginner experience
  • You need Fava’s polished interface
  • You’re starting from scratch

Choose hledger if:

  • You need proven performance at scale
  • You’re migrating from Ledger
  • You prefer CLI workflows
  • You value type safety and functional programming

Avoid Ledger if:

  • You have large datasets (>100k transactions)
  • You’re starting a new project in 2025

Respectful Disagreement

@accountant_alice said “Ledger wins for legacy systems only.” I’d add: hledger wins for anyone who values CLI power, performance, and format compatibility.

Both Beancount and hledger are excellent tools. Choose based on your workflow, not just benchmarks.

Happy to answer questions about hledger’s real-world usage!

Sources:

  • 3 years of professional hledger usage (2023-2025)
  • hledger documentation and CLI reference
  • Benchmark data from @finance_fred’s post

Great discussion! I’ve used all three tools over the past 8 years, so I can offer a migration perspective.

My Journey: Ledger → hledger → Beancount

2017-2020: Ledger

  • Started with Ledger because it was “the original”
  • Worked fine for personal finance (~5k transactions/year)
  • Hit performance issues around 2019 with a client (50k transactions)

2020-2023: hledger

  • Migrated to hledger for better performance
  • Migration was smooth (Ledger format compatibility)
  • Happy with CLI tools and speed

2023-present: Beancount

  • Switched for Python API and Fava
  • Migration was painful (format conversion)
  • But worth it for automation capabilities

The Migration Reality Check

@finance_fred’s benchmarks are great, but migration is the hidden cost of switching tools.

Ledger → hledger: EASY

  • Same file format
  • Copy files, run hledger
  • Fix minor syntax differences
  • Time: 2-3 hours for 10 years of data

Ledger/hledger → Beancount: HARD

  • Different syntax (semicolons vs asterisks, etc.)
  • Different account naming conventions
  • Different balance assertion syntax
  • Need conversion scripts
  • Time: 20-40 hours for 10 years of data

Tools for Migration

ledger2beancount: Automated conversion tool

  • :white_check_mark: Handles 90% of common patterns
  • :cross_mark: Fails on complex transactions
  • :cross_mark: Requires manual cleanup

My experience: Started with 10 years of Ledger data (25k transactions). ledger2beancount converted 80%, I manually fixed 20% (5k transactions). Took me 30 hours over 2 weeks.

When Should You Migrate?

Migrate FROM Ledger if:

  • :white_check_mark: You’re experiencing performance issues
  • :white_check_mark: You need better tooling (Python/Haskell)
  • :white_check_mark: You want active development/community

Stay ON Ledger if:

  • :white_check_mark: Your dataset is small (<10k transactions)
  • :white_check_mark: Performance is fine
  • :white_check_mark: You’re comfortable with the tool

Choose hledger if:

  • :white_check_mark: You want fast migration from Ledger
  • :white_check_mark: You prefer CLI workflows
  • :white_check_mark: You need proven scalability

Choose Beancount if:

  • :white_check_mark: You want Python automation
  • :white_check_mark: You need Fava for clients/visualization
  • :white_check_mark: You’re willing to invest time in migration

The Version Lock-In Problem

@tax_tina raised a good point about Beancount v3. What happens to existing Beancount users when v3 is released?

Questions I have:

  1. Will v3 maintain backward compatibility with v2 files?
  2. Will the Python API change significantly?
  3. Will existing Fava installations work with v3?

hledger has maintained format compatibility across versions. This stability matters for long-term planning.

Performance vs Usability Trade-Off

After using all three tools, here’s my honest take:

Performance matters IF:

  • You have >100k transactions/year
  • You generate reports frequently (multiple times/day)
  • You run complex queries regularly

Performance doesn’t matter IF:

  • You have <50k transactions/year
  • You generate reports monthly/quarterly
  • You mostly add transactions and occasionally reconcile

For 90% of users, the difference between 2 seconds and 80 seconds is irrelevant. You’ll spend way more time on data entry and categorization.

Usability matters MORE:

  • Good documentation saves hours of frustration
  • Python API enables automation (saves hours/month)
  • Fava makes client interactions easier
  • Better error messages reduce debugging time

My Current Setup (Hybrid Approach)

I actually use BOTH Beancount and hledger professionally:

Beancount for:

  • Small business clients (Python automation, Fava interface)
  • Personal finance (integration with other tools)
  • Clients who want visual reports

hledger for:

  • Large enterprise clients (proven scalability)
  • Clients with existing Ledger files (easy migration)
  • CLI-heavy workflows

The tools aren’t mutually exclusive. I’ve learned both, and I use the right tool for each situation.

The Real Question: Investment vs Return

Choosing a plain text accounting tool is an investment:

Time investment:

  • Learning the syntax: 10-20 hours
  • Building importers: 20-50 hours
  • Migration from other tools: 0-40 hours

Return on investment:

  • Lifetime of accurate, auditable financial records
  • Automation that saves hours every month
  • Skills that apply across tools (double-entry concepts)

The tool you choose matters less than your commitment to using it consistently.

My Recommendations by Scenario

Starting fresh in 2025:

  • Go with Beancount (best ecosystem, documentation, future)
  • Or hledger (if you prefer CLI and proven performance)

Currently on Ledger with <50k transactions:

  • Migrate to hledger (easiest path, good performance)

Currently on Ledger with >50k transactions:

  • Migrate to hledger or Beancount (Ledger won’t scale)
  • hledger = easier migration
  • Beancount = better long-term tooling

Currently on hledger:

  • Stay unless you specifically need Python/Fava
  • If you migrate to Beancount, budget 20-40 hours

Currently on Beancount:

  • Stay. You’re in the best position for the future.

Questions for the Community

  1. Has anyone migrated from Beancount back to hledger/Ledger? Why?
  2. What are the biggest pain points in migration?
  3. Is anyone using multiple tools simultaneously (like I do)?

The Bottom Line

All three tools implement double-entry accounting. They all work.

  • Ledger: Legacy option, avoid for new projects
  • hledger: Solid, stable, fast - great choice
  • Beancount: Best ecosystem, Python API, future-proof - also great choice

Choose based on your workflow, not just benchmarks. And once you choose, commit to it. The tool matters less than consistent, disciplined usage.

Sources:

  • 8 years of using Ledger, hledger, and Beancount professionally
  • ledger2beancount migration tool documentation
  • Personal migration experience (2017-2025)