The Ultimate Plain Text Accounting Showdown 2025: Beancount v3 vs hledger vs Ledger

After spending the last 3 months testing all three major plain text accounting tools with the same dataset, I’m ready to share a comprehensive comparison. This isn’t “which is best” - it’s “which is best FOR YOU.”

The Contenders

Ledger - The original, created by John Wiegley in 2003
hledger - Modern Haskell rewrite, emphasizing UX and reliability
Beancount - Python-based, focusing on data integrity and validation

All three are mature, actively developed, and production-ready.

Performance Benchmarks (2025)

I tested with identical datasets on the same hardware (M2 Max, 32GB RAM).

1 Million Transactions Test

Tool Parse Time Throughput Memory
Ledger 6.2s ~161K txn/s 1.5GB
hledger 80.2s ~12.5K txn/s 3.2GB
Beancount v3 25s ~40K txn/s 5.2GB

Winner (performance): Ledger by a wide margin

100K Transactions (More Realistic)

Tool Parse Time Memory
Ledger 0.8s 180MB
hledger 8.5s 420MB
Beancount v3 2.1s 520MB

At typical dataset sizes (< 100K), all three are fast enough that performance isn’t a deciding factor.

Philosophy & Approach

Ledger: Flexibility First

Philosophy: Trust the user, provide maximum flexibility

Account creation: Automatic (just use it)
Validation: Minimal (assumes correctness)
Error handling: Permissive

Example:

2025-11-08 Grocery Store
    Expenses:Groceries    $50.00
    Assets:Checking

If you typo “Groceries” as “Grocerys” - Ledger silently creates a new account. Pro: Fast entry. Con: Easy to make errors.

hledger: Practicality & UX

Philosophy: Balance between flexibility and structure

Account creation: Automatic with warnings
Validation: Moderate (helpful suggestions)
Error handling: Informative

Focus areas:

  • Best documentation in plain text accounting
  • Most user-friendly error messages
  • Web UI included (hledger-web)
  • Designed for beginners AND experts

Beancount: Correctness & Validation

Philosophy: Prevent errors before they happen

Account creation: Explicit declaration required
Validation: Strict (errors halt processing)
Error handling: Detailed and precise

Example:

2025-01-01 open Assets:Checking
2025-01-01 open Expenses:Groceries

2025-11-08 * "Grocery Store"
    Expenses:Groceries    50.00 USD
    Assets:Checking

Typo “Grocerys”? Error: Account does not exist. You fix it before it becomes a problem.

File Format Comparison

Ledger Format

2025-11-08 * Grocery Store
    Expenses:Food:Groceries                $50.00
    Assets:Bank:Checking

hledger Format (Same as Ledger)

2025-11-08 * Grocery Store
    Expenses:Food:Groceries                $50.00
    Assets:Bank:Checking

Beancount Format

2025-11-08 * "Grocery Store" "Weekly shopping"
    Expenses:Food:Groceries    50.00 USD
    Assets:Bank:Checking       -50.00 USD

Differences:

  • Beancount requires explicit amounts (both sides)
  • Beancount uses quotes for payee/narration
  • Ledger/hledger infer second amount
  • Syntax incompatible (can’t just switch)

Feature Comparison

Feature Ledger hledger Beancount
Multi-currency
Stock/commodity
Virtual transactions
Budgeting Plugin
Web UI ✓ (hledger-web) ✓ (Fava)
Python API
Import tools Community Community Built-in
Explicit accounts ✓ (required)
Price history
Tags/metadata

Ecosystem & Community

Ledger

  • Age: 22 years (since 2003)
  • Community: Largest, but fragmented
  • Development: Slower (mature/stable)
  • Documentation: Comprehensive but dense
  • Tools: Many community tools, varying quality

hledger

  • Age: 13 years (since 2012)
  • Community: Growing, very active
  • Development: Most active development
  • Documentation: Best in class
  • Tools: Curated, high quality

Beancount

  • Age: 12 years (since 2013)
  • Community: Developer-heavy, enthusiastic
  • Development: Active (v3 major release)
  • Documentation: Excellent, technical
  • Tools: Fava (outstanding), growing ecosystem

Learning Curve

Ledger:

  • Quickest to start (permissive)
  • Steepest to master (many features)
  • Documentation: Reference manual style

hledger:

  • Gentle learning curve (best docs)
  • Progressive complexity
  • Documentation: Tutorial style

Beancount:

  • Moderate learning curve (stricter syntax)
  • Rewards learning with safety
  • Documentation: Technical but thorough

Use Case Recommendations

Choose Ledger If:

✓ You have huge files (500K+ transactions)
✓ You want maximum flexibility
✓ You’re comfortable debugging issues
✓ You prefer C++ performance
✓ You like terminal-first workflow

Choose hledger If:

✓ You’re new to plain text accounting
✓ You want excellent documentation
✓ You value UX and error messages
✓ You want included web UI
✓ You prefer Haskell reliability

Choose Beancount If:

✓ You want strict validation
✓ You need Python API for automation
✓ You prefer errors over silent failures
✓ You want Fava web interface
✓ You value data integrity over flexibility

My Personal Recommendation Framework

Question 1: Are you new to plain text accounting?

  • Yes → hledger (best documentation and UX)
  • No → Continue

Question 2: Do you need Python automation/scripting?

  • Yes → Beancount (only one with Python API)
  • No → Continue

Question 3: Do you have 500K+ transactions?

  • Yes → Ledger (best performance)
  • No → Continue

Question 4: Do you value catching errors automatically?

  • Yes → Beancount (strict validation)
  • No → Ledger or hledger (both flexible)

Can You Switch Between Them?

Ledger ↔ hledger: Easy (mostly compatible)
Ledger/hledger → Beancount: Converters exist, some manual work
Beancount → Ledger/hledger: Harder (different philosophy)

The Verdict

There is no single “best” tool. All three are excellent and actively maintained.

My take:

  • 2025 “most evolved”: hledger (best balance)
  • 2025 “most powerful”: Ledger (if you need raw speed)
  • 2025 “most innovative”: Beancount (Python API + Fava)

Try multiple tools with the same month of data and see which workflow feels better.

What do others think? Which tool do you use and why?