Skip to content

Jatin2606/LedgerFlow

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LedgerFlow

A payment ledger backend built with Python, FastAPI, SQLAlchemy, and PostgreSQL. LedgerFlow demonstrates backend system design, double-entry accounting logic, concurrency-safe transaction posting, REST API development, Docker-based local setup, and automated testing.

Overview

LedgerFlow simulates the core of a payment ledger system used in fintech, wallet, or settlement platforms. Instead of storing only a final balance, it records every payment as a balanced set of debit and credit entries across accounts.

This project allows us to:

  • create and manage ledger accounts
  • post balanced payment transactions
  • store debit and credit entries
  • calculate account balances
  • validate transaction integrity using double-entry accounting rules

Tech Stack

  • Python
  • FastAPI
  • SQLAlchemy
  • PostgreSQL
  • SQLite
  • Pydantic
  • Docker
  • Pytest
  • Locust
  • k6

Features

  • FastAPI backend with OpenAPI documentation
  • SQLAlchemy-based data layer
  • PostgreSQL for production-style local development
  • SQLite fallback for quick local runs
  • double-entry ledger validation
  • row-level account locking with PostgreSQL SELECT ... FOR UPDATE
  • idempotency-key support for safe client retries
  • account management APIs
  • transaction posting APIs
  • account balance calculation
  • automated tests for core ledger workflows
  • included benchmark scripts for Locust and k6

Architecture

app/
  api/         # Route handlers
  core/        # Configuration and settings
  db/          # Database engine and session management
  models/      # SQLAlchemy ORM models
  schemas/     # Pydantic request and response schemas
  services/    # Ledger business logic
benchmarks/    # k6 and Locust load tests
scripts/       # Utility scripts such as benchmark data seeding
tests/         # Automated API tests

Core entities:

  1. Account
  2. LedgerTransaction
  3. LedgerEntry

Double-Entry Rules

LedgerFlow enforces the following rules:

  • every transaction must contain at least two entries
  • total debits must equal total credits
  • every referenced account must exist
  • accounts must be active
  • account currency must match transaction currency

These constraints keep the ledger balanced, consistent, and auditable.

Setup

1. Clone the repository

git clone https://github.com/Jatin2606/Payment-ledger-.git
cd Payment-ledger-

2. Create and activate a virtual environment

python3 -m venv .venv
source .venv/bin/activate

3. Install dependencies

pip install -e ".[dev]"

4. Create the environment file

cp .env.example .env

Example .env:

DATABASE_URL=postgresql+psycopg://ledger_user:ledger_password@localhost:5432/payment_ledger
APP_NAME=LedgerFlow
API_V1_PREFIX=/api/v1

Running the Project

Option 1: Run with PostgreSQL and Docker

Start PostgreSQL:

docker compose up db -d

Run the API:

uvicorn app.main:app --reload

Option 2: Run locally with SQLite

For quick development, you can run the backend without PostgreSQL. If DATABASE_URL is not set, the app falls back to SQLite.

uvicorn app.main:app --reload

API Access

Once the server is running, open:

  • Swagger UI: http://127.0.0.1:8000/docs
  • ReDoc: http://127.0.0.1:8000/redoc
  • Health Check: http://127.0.0.1:8000/health

Running Tests

pytest

Concurrency Safety

LedgerFlow now protects concurrent posting in two ways:

  • PostgreSQL row-level locking on affected accounts using SELECT ... FOR UPDATE
  • optional idempotency_key support so duplicate client retries return the original transaction instead of double-posting

That means two requests hitting the same accounts will serialize at the database level in PostgreSQL instead of racing through unprotected writes.

Benchmarking

The repo includes both k6 and Locust benchmark scripts:

  • benchmarks/k6_transactions.js
  • benchmarks/locustfile.py

Seed benchmark accounts

python scripts/seed_benchmark_data.py

This prints:

  • WALLET_ACCOUNT_ID
  • SETTLEMENT_ACCOUNT_ID

Run k6

BASE_URL=http://127.0.0.1:8000 \
WALLET_ACCOUNT_ID=<wallet_id> \
SETTLEMENT_ACCOUNT_ID=<settlement_id> \
VUS=25 \
DURATION=30s \
k6 run benchmarks/k6_transactions.js

Run Locust

WALLET_ACCOUNT_ID=<wallet_id> \
SETTLEMENT_ACCOUNT_ID=<settlement_id> \
locust -f benchmarks/locustfile.py --host http://127.0.0.1:8000

Recorded Local Benchmark Results

The following results were measured on April 20, 2026 against POST /api/v1/transactions using:

  • local PostgreSQL 17
  • one local Uvicorn process
  • Locust headless runs for 20s
  • benchmark payload with two ledger entries per transaction
  • row-level locking and idempotency support enabled
Concurrent Users Requests Throughput (req/s) Avg Latency p95 p99 Error Rate
10 1,369 72.98 7 ms 11 ms 35 ms 0.00%
25 3,538 178.65 9 ms 20 ms 36 ms 0.00%
50 6,757 340.51 15 ms 41 ms 56 ms 0.00%

These are machine-specific local results, but they provide real benchmark data for resume bullets and interview discussion.

API Endpoints

Health

  • GET /health

Accounts

  • POST /api/v1/accounts
  • GET /api/v1/accounts
  • GET /api/v1/accounts/{account_id}
  • GET /api/v1/accounts/{account_id}/balance

Transactions

  • POST /api/v1/transactions
  • GET /api/v1/transactions
  • GET /api/v1/transactions/{transaction_id}

Example API Flow

Create a wallet account

curl -X POST http://127.0.0.1:8000/api/v1/accounts \
  -H "Content-Type: application/json" \
  -d '{
    "name": "User Wallet",
    "account_type": "asset",
    "currency": "USD"
  }'

Create a merchant settlement account

curl -X POST http://127.0.0.1:8000/api/v1/accounts \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Merchant Settlement",
    "account_type": "liability",
    "currency": "USD"
  }'

Post a payment transaction

Replace ACCOUNT_ID_1 and ACCOUNT_ID_2 with real IDs from the API.

curl -X POST http://127.0.0.1:8000/api/v1/transactions \
  -H "Content-Type: application/json" \
  -d '{
    "reference": "PAY-1001",
    "idempotency_key": "IK-PAY-1001",
    "description": "Wallet payment capture",
    "currency": "USD",
    "entries": [
      {
        "account_id": "ACCOUNT_ID_1",
        "direction": "debit",
        "amount": "125.00"
      },
      {
        "account_id": "ACCOUNT_ID_2",
        "direction": "credit",
        "amount": "125.00"
      }
    ]
  }'

Check account balance

curl http://127.0.0.1:8000/api/v1/accounts/ACCOUNT_ID_1/balance

Future Improvements

  • JWT authentication and role-based access
  • transaction reversal endpoint
  • Alembic migrations
  • GitHub Actions CI pipeline
  • deployment to AWS, Render, or Railway
  • audit logs and rate limiting

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors