Recca Labs · Selected Work

Case Studies

Real systems, real outcomes. Each engagement is documented twice — the business impact for the team that signs off, and the full technical detail for the engineers who read the code.

01Dual-Currency Educational Platform

Nihada Handa

In Design & Architecture

Business Impact //

  • Guaranteed transactional integrity during simultaneous coin gifting
  • Royalties settled accurately at high billing volume
  • Zero double-spend or corrupted balances under concurrent load

A bank-grade Double-Entry Ledger Engine for an educational platform that mints virtual gold coins, pays dynamic author royalties, and settles high-volume billing — modeled in Next.js 16 and PostgreSQL with optimistic locking to eliminate race conditions.

The Problem

The platform needed a single source of truth for money movement across three interacting systems: learners buying virtual gold coins with real currency, authors earning dynamic royalties on every purchase, and a high-volume billing pipeline that could spike during course launches.

  • Dual-currency accounting — real fiat in, virtual gold coins out.
  • Dynamic author royalties recomputed per transaction.
  • High-volume billing spikes during enrollment windows.
  • Simultaneous coin gifting that could double-spend without guards.

The Solution

We modeled a proper Double-Entry Ledger Engine instead of a single mutable balance column. Every coin mint, gift, and royalty payout becomes an immutable journal entry — a debit on one account balanced by a credit on another — so the books are always provably balanced. Race conditions during simultaneous gifting are neutralized with optimistic locking: each account row carries a monotonically increasing version, and conflicting writes fail fast and retry rather than silently corrupting balances.

  • Immutable journal entries — every movement is a debit/credit pair.
  • Optimistic locking via a `version` column + conditional UPDATE.
  • Idempotent transaction groups to survive retries and partial failures.
  • Row-level balance derived from ledger aggregates, never trusted directly.

Architecture

Next.js 16 App Router

Server Actions + route handlers for ledger mutations.

PostgreSQL

ACID transactions with row-level locking and constraints.

Double-Entry Core

accounts → transactions → ledger_entries with invariant checks.

Optimistic Locking

version column + `UPDATE … WHERE version = $n`.

Implementation

The exact schema — double-entry ledger + optimistic lockingsql
CREATE TABLE accounts (
  id            uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  owner_id      uuid NOT NULL,
  kind          text NOT NULL CHECK (kind IN ('user','author','house','escrow')),
  currency      text NOT NULL CHECK (currency IN ('fiat','gold')),
  balance       numeric(18, 2) NOT NULL DEFAULT 0,
  version       bigint NOT NULL DEFAULT 0,          -- optimistic lock
  created_at    timestamptz NOT NULL DEFAULT now()
);

CREATE TABLE transactions (
  id            uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  idempotency   text NOT NULL UNIQUE,               -- safe retry key
  status        text NOT NULL DEFAULT 'pending',
  created_at    timestamptz NOT NULL DEFAULT now()
);

CREATE TABLE ledger_entries (
  id             uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  transaction_id uuid NOT NULL REFERENCES transactions(id),
  account_id     uuid NOT NULL REFERENCES accounts(id),
  direction      text NOT NULL CHECK (direction IN ('debit','credit')),
  amount         numeric(18, 2) NOT NULL CHECK (amount > 0),
  created_at     timestamptz NOT NULL DEFAULT now()
);
Optimistic locking — a conflict-safe balance mutationsql
-- Read current state, then update only if nobody else has.
SELECT balance, version FROM accounts WHERE id = $1;

UPDATE accounts
SET    balance = balance + $2,
       version = version + 1
WHERE  id     = $1
  AND  version = $3;

-- 0 rows affected -> a concurrent write happened -> retry the whole
-- transaction group (gift, royalty, mint) from the top.

Double-Entry Ledger — core tables

TablePurposeKey columns
accountsOwner, currency, balance and lock version.id · owner_id · kind · currency · balance · version
transactionsIdempotent grouping root for a money movement.id · idempotency · status
ledger_entriesImmutable debit/credit legs that always balance.id · transaction_id · account_id · direction · amount
Next.js 16PostgreSQLDrizzle ORMTypeScriptNode.js
Debits = Credits
Invariant
Lock-safe
Concurrency
Idempotent
Retries
02High-Frequency Crypto Signal Engine

Quant Trader

Active Production

Business Impact //

  • 10,000+ real-time market updates handled with zero data loss
  • 24/7 operation on a single low-cost 2GB server
  • Millisecond signal latency from live order books

A dual-microservice architecture that ingests real-time Binance Futures order books, liquidations, and high-frequency tick feeds on a cheap 2GB VPS — FastAPI, WebSockets, and Redis Stream buffers with Python memory-leak defenses.

The Problem

The client needed to process real-time Binance Futures order books, liquidation cascades, and high-frequency tick feeds 24/7 — but the entire budget was a single 2GB VPS. Python's long-running process model made unbounded memory growth the primary threat: every leaked reference survived forever, and a weekend OOM meant lost signal.

  • Real-time order books and tick feeds at high frequency.
  • Liquidation events that must trigger within milliseconds.
  • A 2GB RAM ceiling on a single cheap VPS.
  • Python long-running processes drifting into OOM kills.

The Solution

We split the workload across two microservices connected by Redis Streams: a fan-out ingest service (FastAPI + WebSockets) that writes normalized frames into bounded Redis Stream buffers, and a signal service that consumes them. Memory leaks are neutralized at the language level — capped deques bound every in-flight buffer, and a customized garbage-collection routine forces generational collection on a schedule so transient objects never accumulate.

  • Dual microservices decoupled through Redis Stream buffers.
  • Capped deques bound every hot path — no unbounded lists.
  • Scheduled `gc.collect()` tuned to generation thresholds.
  • Backpressure: slow consumers drop, never buffer infinitely.

Architecture

Ingest Service

FastAPI + WebSockets fan-out of Binance Futures streams.

Redis Streams

Bounded, replayable buffer between services.

Signal Service

Consumes frames, computes signals, emits alerts.

GC Guards

Capped deques + scheduled generational collection.

Implementation

Memory-leak defense — capped deque + scheduled GCpython
import gc
import asyncio
from collections import deque

class BoundedFeed:
    def __init__(self, maxlen=2048):
        # Capped deque: the oldest frame is dropped automatically,
        # so a stalled consumer can never grow memory without bound.
        self.frames = deque(maxlen=maxlen)

    def push(self, frame):
        self.frames.append(frame)

async def gc_guard(interval=30.0):
    # Forced generational collection keeps short-lived objects
    # from surviving into long-lived generations and leaking.
    while True:
        await asyncio.sleep(interval)
        gc.collect()
FastAPIPythonWebSocketsRedis Streamsasyncio
24/7 stable
Runtime
Bounded
Memory
2GB VPS
Host
03Autonomous Financial Sentiment Pipeline

Market Sentinel

Active Production

Business Impact //

  • 10+ news feeds monitored autonomously in real time
  • Structured, decision-ready sentiment instead of raw text
  • Zero manual triage — alerts routed to your team instantly

An event-driven pipeline that autonomously scrapes 10+ concurrent RSS and news feeds, extracts structured financial sentiment with LangChain, and routes real-time alerts to secure endpoints — built on Node.js.

The Problem

The client needed an always-on radar for financial sentiment across 10+ concurrent RSS and news feeds. The naive approach — a cron job that polled everything and pushed raw text downstream — produced noisy, unstructured data that analysts had to read by hand, and missed the fast-moving stories that move markets.

  • 10+ concurrent RSS and news feeds with no unified shape.
  • Raw text floods that drowned downstream consumers.
  • Latency between publication and actionable alert.
  • No structured extraction — everything was manual triage.

The Solution

We built an event-driven pipeline on Node.js. RSS automated triggers fire on new items, a normalization layer shapes every feed into one schema, and a LangChain structured-output extraction step converts free text into typed sentiment signals — ticker, direction, confidence, and rationale. Alerts are then routed to secure, signed endpoints so downstream systems consume structured JSON instead of prose.

  • RSS triggers fire on publication, not on a polling clock.
  • LangChain structured output extracts typed sentiment.
  • Normalization layer unifies 10+ heterogeneous feeds.
  • Signed alert delivery to secure endpoints.

Architecture

Triggers

RSS automated triggers detect new items in real time.

Normalizer

Maps every feed into a single canonical shape.

Extraction

LangChain structured output → typed sentiment signal.

Router

Signed delivery to downstream secure endpoints.

Implementation

Structured sentiment extraction contracttypescript
interface SentimentSignal {
  ticker: string;
  direction: 'bullish' | 'bearish' | 'neutral';
  confidence: number; // 0..1
  rationale: string;
  source: string;
  publishedAt: string;
}

// LangChain returns JSON conforming to this shape, so downstream
// consumers never touch raw prose — they get typed, signed alerts.
Node.jsLangChainRSSEvent-drivenTypeScript
10+ concurrent
Feeds
Structured JSON
Output
Real-time
Latency