Production systems I designed and built — each with the problem, the design trade-offs, and a flow chart — plus an Ethereum security-token standard I co-authored. Pick any project below to learn more.
Detailed view ·
ERC-1450: RTA-Controlled Security Token
Final
Co-Author · Ethereum Standards Track (ERC)
Open Standard
A standard for security tokens sold under SEC Regulations CF, D, and A, where the Registered
Transfer Agent (RTA) has exclusive control over mints, burns, and transfers. Direct transfer()
and approve() are disabled; holders request transfers via requestTransferWithFee().
It also defines broker registration for compliant secondary trading, read-only ERC-20
compatibility, recovery for lost tokens and court-ordered transfers, and optional EIP-3668
(CCIP-Read) off-chain compliance pre-checks. Listed co-author alongside StartEngine colleagues —
I reviewed the specification and helped implement the backend that supports it.
Created & built · ~94% of the ~45K-line core is my code · StartEngine · 2026
System design
An AI pipeline that clears stalled investments: it finds them, drafts each follow-up, checks every draft with an AI review step, and sends only what passes a safety gate.
Problem
Investments on a regulated crowdfunding platform stall on funding, payment, accreditation, and identity-verification blockers. Clearing them meant piecing together each investor's state across several services and the CRM, then writing a compliant follow-up by hand.
Approach
▸Deterministic intake, AI drafting. Rules classify each stalled case by blocker type; an LLM then triages and drafts. Cases are processed independently, so one failure never fails the run, and the model sees only the data that case needs.
▸Verify, don't trust. An AI review step checks every draft before it goes out. Anything it can't confirm is held for a human — never silently dropped.
▸Safe, idempotent sending. Every automated send passes a safety gate first, and a crash can never send the same message twice. Rolled out in stages, starting with a dry-run phase.
▸Operable without redeploys. Runtime-tunable settings, scoped on-demand refreshes, and long rebuilds as background jobs with status polling instead of requests that time out.
Result
▸Lets a single admin clear 70+ cases per day, with clearer decision-making.
▸The AI review step replaced a brittle hand-maintained rule set after being measured against it on frozen real cases before cutover.
sync callasync / eventmain pathdata storeperson / triggerexternal system
Refresh → case builder → AI drafting agent → AI review step → auto-send → email / SMS; anything unverified is held for a human.
Created & built · authored the design doc · StartEngine · 2026
System design
An LLM operations agent in Slack that answers from live platform data — and whose sensitive account changes require a server-enforced human approval.
Problem
Sales and ops staff wanted to ask investor questions in plain English and sometimes have the assistant carry out authorized account operations. Free-text approval in a chat can't safely authorize a money or account action on its own.
What it can do
Dozens of read and action capabilities, loaded on demand by a router instead of one giant prompt — for example, where an investment stands, how a payment changed over time, or a holdings summary. Sensitive account changes run only through the approval flow below; lower-risk actions run directly.
Approach
▸Approve a stored proposal, not the model's words. A propose step reads live state, stores the exact proposed effect on the server, and posts a plain-language preview. Execution runs from the stored proposal, so the model can't alter what a human approved.
▸The server verifies authorization. The server — not the model — confirms a trusted approver authorized this specific proposal and re-validates against live state at execution. Every approval path converges on the same check.
▸Exactly-once, safe execution. An approved action runs only once; anything unclear goes to a human.
▸Model interprets, server confirms facts. Answers come from server-side lookups that return facts with provenance — or an honest “unknown”. Hard gates remain on sensitive actions. Scoped per deployment, with operator controls.
Result
▸Validated with a deterministic offline eval harness against frozen baselines before cutover: approval recognition and wrong-refusal rates both improved materially, and sensitive actions took fewer turns to complete.
▸Authored the implementation-ready design doc.
sync callasync / eventmain pathdata storeperson / triggerexternal system
Ops user → LLM agent → stored proposal + preview → human approval → approved action runs → account system; the result returns to the thread.
PythonSlackPydantic AIRedisPostgreSQLLLM evals
Campaign Updates Pipeline
Created & built across two services · StartEngine · 2023
System design
Companies raising capital post updates for investors and followers; staff review and schedule each one, and a work queue fans it out to the right audience at publish time.
Problem
Updates needed a staff review step, scheduling, delivery to the right audience — public followers vs. existing investors for private updates — and automatic notices when an offering changed materially.
Approach
▸Explicit lifecycle with role-based permissions. Draft, staff review, scheduled, published. Issuers act only on their own offerings; only staff approve, reschedule, or reject — and rejecting an approved update cancels its pending delivery.
▸Cross-service hand-off with retries and defined reschedule/cancel semantics, so the two services never disagree about what is scheduled.
▸Set-based fan-out into a database work queue. One query builds the per-recipient queue; parallel workers claim work without collisions and emit one notification event per recipient over Kafka.
▸Event-driven closure and migration. A completion event marks the update published; a listener turns material-change events into templated notices (the template is ops-editable config, not code); a strangler path migrated legacy updates.
Result
▸In production across both services since March 2023, replacing a multi-day manual process with a minutes-long workflow.
sync callasync / eventmain pathdata storeperson / triggerexternal system
Issuer + staff → campaign service → offerings delivery queue → fan-out workers → Kafka → email + push; a completion event marks the update published.
JavaSpring BootSpring Data JPAPostgreSQLKafka
Share-Transfer Workflow
Created & built · ~86% of the production code · StartEngine · 2026
System design
Investors move private-company shares to family, a trust, or another account; every signature is collected in a safe order, and the request is handed to the ownership ledger, where the transfer agent's existing approval still applies.
Problem
Transferring privately held securities takes several parties signing legally binding documents in a safe order, and the same shares must never be allocated twice.
Approach
▸A state machine owned by the domain. One allowed-transition table guards every move. Recipients sign before the transferor, so nobody commits shares to a transfer a recipient later declines.
▸The database is the arbiter. Row-level locking and a share reservation make double-allocation impossible even when job runs overlap; investor-facing access is scoped to the requesting account.
▸Background jobs, not synchronous chains. Document generation, signature polling, and outcome reporting run as resilient scheduled jobs with per-item failure isolation. Permanent failures go to a manual queue rather than auto-cancelling, which would email the investor.
▸Replay-safe hand-off, notify after commit. The ledger hand-off is atomic and idempotent and is created unapproved, so the transfer agent's human approval stays downstream. Lifecycle events publish only after commit, so a rolled-back write never notifies anyone; ambiguous e-signature responses go to reconciliation, not automatic retries.
Result
▸In production since September 2026; 34 test files cover the workflow, including explicit account-scoping denials.
sync callasync / eventmain pathdata storeperson / triggerexternal system
Investor → transfer service ↔ e-signature provider → ops review → ownership ledger; events publish after commit and become one email per person.
JavaSpring BootPostgreSQLKafkaE-signatures
IRA Custodian Integration
Primary engineer · built out from a teammate's initial scaffold · StartEngine · 2025–26
System design
Investors open a self-directed IRA, roll assets in from another institution, and invest IRA money in private offerings — kept in sync with an external custodian through background jobs and webhooks.
Problem
The custodian is a third-party system with its own account lifecycle, maintenance windows, e-signature steps, and asynchronous status changes. The platform had to keep investor-facing state correct without tying user requests to the custodian's availability.
Approach
▸Never block a user on the custodian. Custodian work runs in background jobs with per-request transactions and retry; requests stay pending through the custodian's maintenance windows.
▸Store-then-process webhooks. Callbacks land in an inbox first, then are dispatched to handlers, so bursts and duplicates never corrupt state.
▸Two keys to activate. An account activates only when both the custodian and internal checks agree; duplicate callbacks are idempotent and conflicting work is serialized.
▸Replay-safe events. Registration events to Kafka can be re-run safely, so the repair path actually works.
Result
▸In production since March 2025.
sync callasync / eventmain pathdata storeperson / triggerexternal system
Investor → account service → background jobs ↔ IRA custodian; custodian webhooks land in an inbox, then update the account service.
JavaSpring BootPostgreSQLKafkaWebhooks
AI Document Intake
Built much of the validation & auto-fill layer · ~64% of surviving subsystem code · StartEngine · 2024
System design
Founders upload corporate documents; an AI extraction service reads them asynchronously, and the onboarding service validates each result and auto-fills structured onboarding data — only while onboarding can still accept it.
Problem
Onboarding a company to raise capital takes dozens of facts that live in legal and financial documents. Re-typing them is slow and error-prone, and extracted data should only land while onboarding can still accept it.
Approach
▸Asynchronous by design. An upload emits an extraction request over Kafka; results come back on a separate topic. A colleague built the Kafka plumbing; I built what happens to each result.
▸A typed contract per document type. Results are validated before they touch the domain; a violation marks the upload as an error with a reason instead of writing bad data.
▸Stage-guarded writes. Extracted data is applied only when the onboarding stage permits; rejected results are ignored or recorded, never applied.
▸Prerequisite-aware second pass. A lock-guarded scheduled job requests a company-level extraction once the needed documents exist. A Q&A endpoint lets users ask questions about the documents they uploaded.
Result
▸In production since July 2024; document types expanded through 2024.
Created & built · ~72% of the service's code · StartEngine · 2024
System design
An event-driven service that turns onboarding documents — scanned PDFs, Word files, images, spreadsheets — into structured JSON, with OpenAI, Anthropic, and Gemini behind one routing layer.
Problem
Every company that onboards uploads a stack of legal and corporate documents. Reviewers had to read each one and re-key the facts by hand.
Approach
▸A request queue in front of the AI. The Kafka consumer only records the request, and a worker picks it up. Slow LLM calls never back up the consumer, and every request has an auditable state — at the cost of one extra hop.
▸Classify, then extract. An LLM identifies the document type when it's unknown; a versioned, type-specific prompt library drives extraction, hardened against instructions embedded in the documents themselves.
▸Multi-provider routing with fallback. Inputs route to the best-fit provider by input type, with fallback and an optional cross-provider merge for field coverage — trading cost and latency for accuracy.
▸Protected results, closed loop. Sensitive fields are encrypted and values normalized before storage; results and handled errors return to onboarding over Kafka.
Result
▸Cut document processing time from 30 minutes to 2–3 minutes and lifted accuracy from 30% to 70%.
▸In production since July 2024; three other engineers later extended the design.
Related: AI Document Intake — how onboarding validates and applies this service's results.
sync callasync / eventmain pathdata storeperson / triggerexternal system
Onboarding service → Kafka → request queue → extraction worker ↔ AI providers → stored securely → results back over Kafka.
PythonKafkaPostgreSQLOpenAIAnthropicGeminiAWS
JordoBot9000
Creator · deployed at StartEngine · open-sourced (MIT) · 2026
StartEnginePersonal Project
A self-hosted AI code reviewer for a team pull-request workflow: it watches a GitHub organization, queues PRs in Postgres, runs headless Claude Code over each one, and posts exactly one decisive review under its own bot account.
Problem
It started as a passion project for a few engineers and grew as more asked for reviews. An AI reviewer with shell access over untrusted PR content, whose approval can carry weight, needs hard limits: no re-reviewing unchanged code, no reviewing mid-push or while CI is running, no runaway on a busy PR, and nothing posted that policy forbids — whatever the prompt or the diff says.
Approach
▸Tiered detection and re-look. Configurable polling for reviews requested from the bot, from a team, and a proactive sweep of configured repos; a push, a human reply, or CI turning green brings a reviewed PR back.
▸Idempotent queue keyed by head commit, with daily caps — a re-poll never re-reviews unchanged code and every reply earns exactly one follow-up.
▸Cost gates before the model runs. A debounce waits for the author to stop pushing and a CI gate waits for checks (both fail open). A newer commit cancels a running review and keeps partial findings.
▸Guardrails in code, not the prompt. Every post goes through a per-run shim that allows exactly one review shape and re-checks dry-run mode, approval policy, and PR state at post time; the model's environment has no database access.
▸Two verdicts, human-held approvals. Approve or request changes — never a neutral comment. Approvals are opt-in per author; held approvals wait for an operator in a web dashboard that also edits runtime settings (pause, dry-run, model, concurrency).
Result
▸Became the team's sole AI code reviewer, replacing CodeRabbit — cheaper, with reviews engineers preferred.
▸The self-hostable core (Docker Compose) is MIT-licensed with offline tests for approval rules, concurrency, caps, and the post-time gate. Production deployment config is not in the repo.
sync callasync / eventmain pathdata storeperson / triggerexternal system
GitHub org → detection + hold gates → Postgres queue (operator dashboard) → worker running headless Claude Code → post-time policy shim → one review; a push, reply, or green CI brings the PR back.
PythonPostgresDockerClaude CodeGitHub APIFastAPI
Predictive Planning Data Integration
Primary developer · Wolters Kluwer · 2016–2021
Wolters Kluwer
Primary developer for Vanguard Predictive Planning data integration — custom connectors that
processed millions of records and cut data preparation from weeks to under 30 minutes. Also
designed custom data tables for brand-specific forecasting systems (Lenox, LG Hausys).
JavaPostgreSQLData Integration
Jazz Foundation
Software Engineer Co-op · IBM · 2015–2016
IBM
Contributed to a collaborative lifecycle management web app for the Jazz Foundation group using Java.
JavaWeb App
System design · StartEngine
Pick a system to open its story and flow chart above.
Co-founder of an Asian-inspired specialty café in Durham, NC. SoMii is a community-forward
space featuring specialty coffee, Asian-inspired flavors, and soft serve —
blending culinary craft with a welcoming, design-forward environment.
A venture that brings together product thinking, brand design, and community building
in a completely different domain than software — and all the more exciting for it.