Work

Four production systems, told the way architecture actually happens: the context, the constraints, the decisions, and what broke along the way.

View Full GitHub Profile
Data Platform · AWS · 2026

Builder Performance Platform

Context

Performance conversations for thousands of technical employees at AWS ran on data scattered across systems, with every team assembling its own picture. The answer was a four-application analytics ecosystem on one shared data foundation — a profile view, goals, and talent tooling — tracking 70+ metrics per person for individual contributors, managers, and operations teams.

Constraint

Seven weeks to launch, five-plus business units with different workflows to align, and zero tolerance for access mistakes: this is per-person performance data, so row-level security has to be provably correct, not approximately correct.

Decisions

As the architecture partner on the data layer, I pushed for one modular SQL query per metric — 70+ small, reviewable units instead of monolithic queries, so a single metric can fail, be fixed, and be reviewed in isolation. Navigation went filter-based rather than parameter-passing: less clever, but predictable and safe with multi-select. Targets were kept out of the profile entirely and live in a separate application — a separation of concerns that kept each app simple. I also automated the deployment workflow from 20+ manual steps down to 3–5.

What broke

Four production-blocking data quality issues surfaced in the run-up to launch. The best one: a customer engagement metric that was quietly inflated because it summed where it should have counted distinct. Another metric was broken because two teams were using the same program name for different things — a bug that lived in vocabulary, not code. Both taught the same lesson: at this scale, data quality is an organizational problem wearing a technical costume.

Outcome

Launched May 2026 and adopted as the designated data source for official review cycles across multiple AWS organizations. The deployment automation alone saves hours every week, and the modular metric architecture means new business units onboard without touching existing ones.

Data Modeling Modular ETL Row-Level Security Amazon QuickSight SQL · Python
Data Platform · AWS · 2024

Customer Adoption Acceleration Program

Context

When generative AI reset the competitive landscape, AWS field teams suddenly needed to coordinate technical validation work across more than 25 specialist units — each with its own intake process, its own tooling, and its own definition of an "opportunity." There was no central mechanism to route requests or alert the right team when a new workload appeared.

Constraint

The hard part was never the pipeline. It was that 25+ teams had 25+ workflows, and every one of them had good reasons for working the way they did. Any system that required teams to abandon their process would simply not get adopted. It also had to ship fast — the business context was moving weekly.

Decisions

I led requirements gathering across all of the teams, then designed the data integration and delivery architecture from scratch: a unified intake model, automated routing logic, and opportunity tracking that met each team where it already worked instead of forcing a new tool on them. I traded elegance for adoption at several points — a messier data model that mapped to how teams actually operated beat a cleaner one they would have ignored.

Outcome

The system processed thousands of technical engagements with 92% automated routing, became the coordination backbone for the program, and was featured in a launch announcement to senior field leadership. The lesson I keep from it: at organizational scale, requirements synthesis is the architecture.

Requirements Synthesis ETL Architecture Data Modeling Automated Routing SQL · Python
Serverless Edge · Production

Gather at Alcove

gatheratalcove.com — live in production

Context

An event platform where multiple organizers run their communities on shared infrastructure. Multi-tenant from day one, which means the most important design question is the least glamorous one: how do you guarantee one tenant can never see another tenant's data?

Constraint

One builder, no budget for idle servers, and no tolerance for a security model that depends on every future line of application code being written correctly.

Decisions

I put tenant isolation in the database itself — PostgreSQL row-level security on Supabase — rather than in application code, with JWTs validated at the Cloudflare edge before requests ever reach data. App-layer checks fail open when someone forgets one; RLS fails closed. Cloudflare Workers and Pages keep fixed infrastructure cost at effectively zero, with CI/CD on GitHub Actions.

What broke

The design got its trial by fire in production: an implicit PostgreSQL type mismatch caused RLS policies to fail on live traffic. Debugging a security boundary while it's actively enforcing (or not enforcing) itself teaches you more about the failure modes of zero-trust design than any diagram. The policies now have explicit casts and tests.

Outcome

Live in production with real organizers and real events, running on infrastructure that costs almost nothing at rest and enforces isolation at the lowest layer of the stack.

Cloudflare Workers/Pages Supabase PostgreSQL Row-Level Security JWT / Google Auth Twilio · Resend GitHub CI/CD
Serverless · AI

Ask Chris

Running on this site — open the chat and ask it how it works

Context

An AI assistant on a personal site is a public, unauthenticated endpoint attached to a metered API. That makes it less an AI problem than a cost-control and abuse problem: anyone on the internet can spend your money.

Constraint

Zero fixed infrastructure cost, a hard monthly budget, and no ops burden — it has to run itself.

Decisions

AWS Lambda and DynamoDB, with cost control enforced in layers: per-user daily limits, a global daily cap as the backstop, and SNS alerts when thresholds trip. Conversation memory persists in DynamoDB so the bot holds context across a session without a server holding state. It took three architecture passes to land here — each one prompted by a real security or persistence problem the previous version couldn't handle.

What broke

My favorite bug: responses generated successfully, then the Lambda crashed anyway — a 500 after the model had already answered. DynamoDB returns numbers as Python Decimal objects, which json.dumps() can't serialize. The answer existed; the response envelope couldn't carry it. Found via a homemade "flight recorder" that captured full tracebacks to the browser console, fixed with explicit casts.

Outcome

A production AI feature that costs nothing at rest, can't blow its budget, and doubles as a live demo — its own architecture is in its knowledge base, so you can interrogate the system about itself.

AWS Lambda (Python) Amazon DynamoDB Google Gemini 2.5 Flash Cost Controls SNS Alerting
Machine Learning · Production

FPL Intelligence Engine

chriseyebagha.com/fantasy — live and self-updating

Context

Fantasy Premier League rewards squad and captain decisions made from incomplete information, fifteen minutes before a deadline, every week for ten months straight. I wanted a system that made that decision better than I could by hand, and that kept doing it without me.

Constraint

It had to run unattended for an entire season: new data every gameweek, a model that doesn't quietly go stale, and a public output, so there was nowhere to hide if a prediction was wrong.

Decisions

Six separate XGBoost models, each specialized on a different signal (form, fixtures, price, minutes risk) rather than one model trying to learn everything at once. A Python pipeline pulls the official FPL API, retrains, and regenerates squad and captain recommendations automatically each gameweek. The frontend rebuilds and redeploys on that same schedule with no manual step in between.

What broke

The uncomfortable engineering decision was the scoreboard: a page that tracks the model's own hit rate against reality, gameweek by gameweek, permanently public. It would have been easier to only show the wins. I built it anyway, because a prediction engine that hides its record isn't one worth trusting, including by me.

Outcome

A production system that has run a full season end to end without hand-holding, plus a technical writeup ("Under the Hood") and manager's guide for anyone who wants to see the model's reasoning, not just its picks.

Python · XGBoost Next.js · TypeScript Self-Updating Pipeline GitHub Actions FPL API