How I Actually Build Things
Not a features list: the actual decisions, trade-offs, and reasoning behind the revenue-generating systems I've shipped, from payments to scheduling to the backend architecture holding them up. Disagree with a call I made? Say so below.
Making money the source of truth, not the client
TaskForce App, Founding Backend Engineer (Part-time)Early-stage subscription SaaS was losing ARR growth quietly. A one-shot Stripe charge had no recovery path: a single declined card meant a lost subscriber with no second attempt, and nothing in the product surfaced that risk until churn showed up in the numbers.
- Built a webhook-driven billing state machine instead of trusting client-side "payment succeeded" callbacks. Stripe's webhook events are the only source of truth for anything financial.
- Added a staged dunning schedule (multiple retries plus card-update prompts) instead of a single retry, so a temporarily declined card gets several honest chances before the subscription lapses.
- Made every webhook handler idempotent, keyed on the Stripe event ID, since Stripe retries delivery and a naive handler would double-charge or double-count revenue.
Synchronous "charge now, confirm now" is simpler to build and feels instant. Webhook-driven billing adds a short lag between charge and confirmation. I chose the lag: a ledger that can be wrong is a worse trade than a ledger that is occasionally slow.
Trusting a client-side confirmation for money is how a paid feature stays unlocked on a failed charge. The write path has to be the one thing that can't be spoofed or dropped.
Double booking is a database problem, not a UI problem
Stackron, HealthTech (contract project)A clinic-scheduling tool needed a hard guarantee that two patients could never be booked into the same slot, in a healthcare context where patient-clinic messaging also had to stay confidential.
- Enforced slot uniqueness as a database constraint instead of an application-level "check, then write." Application code checking availability cannot survive two simultaneous requests.
- Treated the booking write itself as the point of truth: if the constraint rejects it, the UI shows the slot as taken and re-fetches, instead of trusting a stale in-memory read.
- Layered encrypted messaging on top so patient-clinic communication stayed confidential without adding friction to the booking flow.
An application-level lock is faster to ship and reads cleaner in review. A database constraint means an extra migration and a less "clever" codebase. I chose the constraint: a double-booked patient is a trust-breaking incident, not a bug ticket.
"Is this slot free?" followed by "then book it" is a classic time-of-check-to-time-of-use race under real concurrency. The guarantee has to live where the write actually happens, not in the component that asked the question.
Fast and correct, not fast instead of correct
HiddenShelves, Frontend EngineerA storefront needed to load fast and hold strong Core Web Vitals during peak traffic, but earlier attempts at caching product and pricing data eventually served a stale price or a sold-out item as available.
- Indexed the queries that actually ran in production first, using real query plans against catalog and cart reads, instead of reaching for a cache to paper over a slow, unindexed query.
- Layered caching on top of that indexed baseline, with invalidation tied to the write that changed the data (a price update, a stock change), not a blanket time-to-live.
- Built a composable checkout module (promotions, gift options, dynamic shipping) as independent, testable rules instead of one branching checkout function.
Caching everything for a few minutes is the fastest way to a good Lighthouse score, and the easiest way to sell a customer a sold-out item. I chose more invalidation plumbing over a faster demo and a slower trust problem.
A cache papers over a missing index. It doesn't replace one, and it doesn't know the truth underneath it changed unless you tell it. Index first, cache what's left, invalidate on the write.
Isolating tenants before they isolate each other's uptime
Umwelth, Lead Frontend EngineerA B2B rewards platform serves 50+ enterprise clients from one codebase. One noisy client's traffic, data, or bad deploy can't be allowed to degrade another's.
- Designed a micro-frontend architecture with per-tenant data contracts, so a deploy or an incident for one client is isolated instead of an all-or-nothing release.
- Chose availability over strict consistency for parts of the platform where a few seconds of staleness is invisible (activity feeds, dashboards), and strict consistency for anything touching a reward balance.
- Coordinated data contracts directly with backend and platform teams so a schema change on one side could not silently break the other.
One shared, tightly consistent data layer is simpler to reason about. Splitting consistency guarantees by endpoint is more design work up front. I chose the split: a stale dashboard is a shrug, a wrong reward balance is a support ticket and a broken promise.
The CAP trade-off isn't a one-time choice for the whole system. Under a partition, a reward-balance endpoint should fail closed (consistency); an activity-feed endpoint should fail open (availability). Treating every endpoint the same wastes either uptime or trust.
Decoupling what happened from who needs to know
Umwelth, Lead Frontend EngineerUsers need to know the moment a reward posts or an account needs attention, but calling the notification provider inline, inside the same request that changed the data, means a slow email or push provider stalls the action that triggered it.
- Treated every state change worth notifying about as an event, published onto an asynchronous messaging layer, instead of calling a notification provider inline.
- Let each channel (email, in-app, client webhook) consume the same event independently, so adding a channel never means touching the code that produced the event.
- Made consumers idempotent on the event ID, since the messaging layer guarantees at-least-once delivery, not exactly-once.
An inline notification call is one function away and easy to trace. An event bus is more infrastructure and a harder debugging story. I chose the event bus: the core action has to stay fast even when a third-party provider is slow or down.
Coupling "the reward posted" to "the email sent" means the flakiest third-party provider now dictates how fast your core product feels. Decoupling with events keeps the user-facing path fast and lets delivery retry independently.
A feature name can't cover more ground than its mechanism does
DepVault, Founder Project — Published to npmDepVault computes a predictive Trust Score for packages across npm, PyPI, Cargo, and Go, and ships a pre-install security gate so a risky dependency gets caught before it lands. Two problems showed up once real users touched it: an attacker-controlled package could make the scoring itself expensive enough to be a denial-of-service vector, and re-enabling the scan on every project meant setting an environment variable by hand each time, so it quietly stopped happening.
- Bounded the Trust Score computation itself: the Monte Carlo simulation, Shannon entropy, and AHP weighting all run under memoization and a hard iteration cap, so attacker-controlled package metadata can no longer turn the scan into the DoS vector it was meant to catch.
- Replaced env-var-per-install friction with a persisted CLI flag (--enable-auto-scan) that writes to ~/.depvault/auto-scan.json, so every future npm install of a project depending on it scans automatically until explicitly turned off.
- Added --block-on-critical as real, narrowly-scoped enforcement: a scanned dependency with a known CRITICAL-severity CVE fails the install with exit 1 instead of printing a warning nobody reads, with a DEPVAULT_SKIP_AUTO_SCAN=1 escape hatch for the one-off install that needs to bypass it.
- Named the feature for exactly what its mechanism covers instead of what it sounds like it should cover, and documented the boundary directly in both READMEs.
A plain npm package can't replicate a system-wide install shield: its postinstall script only fires while that package itself is being installed, so it has no hook into a later, unrelated npm install of something else. That requires a CLI with its own shell-wrapper hooks, not an npm postinstall script. I shipped the honestly-scoped version, auto-scan plus block-on-critical on this package's own install path, over a name implying protection the mechanism doesn't provide.
A security feature that implies broader coverage than its mechanism provides is worse than no feature, because someone will eventually rely on the gap it doesn't actually close. The claim has to be scoped to what the hook can really reach.
System Design Principles I Actually Use
Source of truth lives at the write path
Payments, bookings, anything irreversible: the server-side write decides, never the client-side confirmation.
Idempotency on every write endpoint
Not just payments. Webhooks, retries, and queue consumers all redeliver, so any endpoint that isn't idempotent will eventually get called twice.
Index before you cache
A cache hides a missing index, it doesn't fix one. I check the query plan before reaching for Redis.
Cache invalidation is event-driven, not time-based
A TTL is a guess about how often data changes. Invalidating on the write itself is a guarantee.
The CAP trade-off is per-endpoint, not system-wide
A payment endpoint fails closed under a partition (consistency). An activity feed fails open (availability). One system, two different answers.
Isolate at the data layer before the UI layer
A dropdown that hides other tenants' data isn't isolation. A query that can't reach it is.
Ship the boring, reversible decision first
Microservices, event buses, and message queues earn their complexity when a measured bottleneck demands it, not on day one.
A feature's name can't promise more than its mechanism
A postinstall hook only fires on its own package's install, not on some unrelated install afterward. If the mechanism doesn't cover it, the docs say so before anyone assumes it does.
Pitfalls I Watch For
Mistakes I've made, caught in review, or inherited from a codebase, and now check for by default.
Trusting client state for money or bookings
If a client can lie about it, assume one eventually will. Verify on the write path, server-side.
An unindexed query that is only slow at production scale
It works fine against a seed database with 50 rows. Check the query plan against real volume before it ships.
Caching without an invalidation story
A cache with no eviction plan is a bug with a delay timer.
A webhook or retry handler that is not idempotent
It will get called twice. The only question is whether that is safe when it happens.
Notifications fired inline with the action that triggered them
A slow email provider becomes a slow checkout button. Decouple with events.
One consistency model applied to every endpoint
Not every read needs the guarantee a payment does. Matching them wastes availability for no reason.
Technical Calls, Business Outcomes
Three moments where a technical decision turned into an outcome the founders or leadership actually noticed.
Early subscription revenue was flat month over month despite steady signups.
Traced it to failed-payment churn rather than signup drop-off, and rebuilt the retry flow with staged dunning instead of a single retry.
Cut failed-payment cancellations 25% and gave the founders a concrete retention lever to point to.
Pre-launch QA on a clinic-scheduling feature surfaced a race condition: two rapid bookings for the same slot both appeared to succeed.
Flagged it before launch as a trust risk, not a cosmetic bug, and moved the guarantee from application code into a database constraint.
Shipped without a single double-booking incident, in a context where one would have been a compliance problem, not a support ticket.
API response times were creeping up heading into a peak sales window, with checkout timeouts starting to show in monitoring.
Traced it to missing indexes and a caching layer with no real invalidation strategy, and fixed both before the traffic spike instead of scaling hardware to mask it.
40% faster API responses and 99.99% uptime through the exact peak-traffic window revenue depended on.
Discuss this
Disagree with a decision, hit a similar problem, or want the trade-offs explained further? Drop a comment. I read every one and reply here myself, usually within a few days.
No comments yet. Be the first to weigh in.