Software · 2025
Parkzy
Driveways, garages, and private lots — booked in seconds from real people in your neighborhood. A peer-to-peer parking marketplace, live on the App Store with a 4.9★ rating and 2,400+ downloads. My company; built end-to-end.
Skip the Search. Ping a Host Instead.
The whole product, frame-accurate: this walkthrough is rendered from code with Remotion — the same pipeline that renders Parkzy's App Store previews — so it's always the current app. The steps follow along as it plays; tap one (or scrub) to jump anywhere.
Live map at useparkzy.com ↗
How It Works
Tell us where you're going. Search a destination — SoFi, USC, a friend's apartment in Echo Park. We surface hosts within walking distance.
One tap. Real humans respond. Parkzy pings every nearby host at once — hosts accept in real time — the matching system is built for sub-60-second accepts.
Drive up. Pull in. Done. Your host's address, access notes, and a live chat thread are waiting.
“I listed 12 of my spots on Parkzy and was able to successfully rent out all of them. They earned me $600 in just one night from an event.”— five-star App Store review
On the App Store




The real App Store listing — “Stop Circling for Parking. Name your price and book a private spot in seconds.”
For spot hosts
List in seconds
Put an unused driveway, lot, or private space online in under a minute.
Earn automatically
Get paid every time a driver parks — pricing, scheduling, and availability all in your control.
Accept from the lock screen
v2.2 — approve or decline a parking request straight from the notification, without opening the app.
For drivers
Guaranteed parking
Find a spot when you actually need it — book last-minute or reserve ahead.
Pay in-app
Apple Pay and Google Pay through Stripe. No cash, no Venmo, no sketchiness.
Talk to a human
A live chat thread with your host — access notes, voice messages, gate codes.
Under the hood
The shape of it
490 SQL migrations, 163 Supabase edge functions, and 3,989 commits in the first year — built and operated as sole engineer since Sept 2025.
One codebase, three platforms
React 18 + Vite + TypeScript, shipped to web, iOS, and Android through Capacitor 7 — with Capgo for over-the-air updates so a fix doesn't wait on app review.
Payments & identity
Stripe Connect for host payouts plus Stripe Identity for ID verification — the trust layer a stranger-parks-in-your-driveway marketplace actually requires.
Geospatial search
Mapbox GL with supercluster, so thousands of spots cluster and re-rank smoothly as you pan.
Tested, not hoped
6 Playwright end-to-end specs (guest booking, auth booking, pricing, Safari), Vitest units on the pricing engine, and a Deno test on the edge functions — all gated in GitHub Actions.
Data warehouse
A separate dbt + BigQuery stack lands PostHog, Supabase, and Stripe data in one place, so product questions get answered with SQL instead of vibes.
Disaster recovery — the part nobody sees
Parkzy runs on Supabase, which means Supabase is a single point of failure for a business that takes people's money. So there's a Terraform-managed AWS standby: an RDS Postgres 17 instance configured for logical replication to match Supabase's defaults, standby Lambdas covering the critical paths (auth, spot search, profile, payment methods, health check), and a GitHub Actions cron that syncs the database every four hours.
It's applied infrastructure, not a diagram — the Terraform state is on disk. Most solo products don't have a failover story. This one does, because a marketplace that can't take a booking is a marketplace that's dead.
The AI suite, shipped
All of it is in production, not in progress: semantic spot search (pgvector embeddings, with a backfill function), LLM-explained dynamic pricing, AI-graded listing photos, message translation, audio transcription, and AI-drafted support replies — all routed through one shared LLM/embeddings helper so every function gets model access the same way. That shared helper is the small, honest version of the model-access layer a platform team builds at real scale.
Live at useparkzy.com ↗.
A real ML pricing engine — not an API call
Dynamic pricing runs on a separately deployed Python service: a scikit-learn GradientBoostingRegressor behind FastAPI, Dockerized, with Prometheus metrics, health/readiness probes, and endpoints for pricing, hourly curves, retraining, and a booking-outcome feedback loop. It runs in shadow mode first — an operator sandbox compares the model's price against the live price on real inventory — and rollout is gated behind a master switch plus a per-host allowlist. An LLM explains the price to users; the number comes from the model.
Inside the machine
A 23-Agent AI Company
Parkzy is operated with a 23-seat AI organization: engineering seats, a board with a duty to dissent, and rituals engineered against sycophancy. It has produced 233 versioned PRDs. The agents propose — I decide.
The org chart
Twenty-three agent seats, each a written role definition with standing responsibilities: leadership (a chief-of-staff CEO seat that synthesizes into decision memos, plus a program manager), a five-seat board (market strategist, legal & risk, CFO, a wildcard — and a customer advocate, because the voice of drivers and hosts holds a board seat on purpose), eleven technical seats (frontend, backend, iOS, Android, UX, AI, DevOps, QA, data, security, and a collector whose whole job is making sure concerns never evaporate), trust & safety, and four marketing seats. Premium models take the judgment lanes; cheaper models take the scan-and-draft lanes.
The rituals
Weekly board meeting
Metrics get refreshed first, then six seats write positions independently — before a clash round where each seat must attack the most dangerous claim on the table. The CEO seat compresses it into a memo of at most three decisions, with dissent preserved verbatim.
Weekly engineering cycle
Twelve seats report evidence-backed concerns plus one mandatory challenge to another seat's work. A collector triages everything into a task board with a hard WIP cap of 10.
Marketing sprint
Every one to two weeks, the four marketing seats run the same propose-clash-decide loop on growth work.
The hard problem is sycophancy
A room full of agreeable AI agents is worse than useless — it launders your own biases back to you with confidence. So the mechanisms are the product: a duty to dissent written into the charter (“silence is a failed contribution”); independent-then-adversarial structure so positions form before they can converge; standing adversaries built into the seat definitions — the wildcard generates, the CFO finds the cheapest falsifying test; QA blocks, the CEO seat pushes ship-speed; trust & safety adds friction, the market strategist defends supply; evidence rules — no number without a source, and “unknown” is an acceptable answer, which kills the failure mode where confident agents out-argue correct ones; a dissent ledger where every decision carries a review-by date and seats earn credibility retroactively for dissents that proved right; and the collector guarantee — every raised concern lands on the board, in the backlog, or gets rejected in writing.
What it produces — and who decides
To date: 233 versioned PRDs, 35 dated decision memos, and shared state files (decision log, experiment queue, risk register, task board) that persist across sessions — the organization has memory. The boundary is explicit in the charter: no agent makes irreversible business decisions, spends money, or deploys to production on its own. Every seat advises, drafts, builds, or critiques; my cofounder and I make the calls. That's not a limitation of the system — it's the design. The interesting discovery after months of running it: the value isn't automation, it's structured disagreement on tap.
Getting Money Right
How Parkzy moves real money without losing a cent: an IOU ledger, a two-phase commit against the double-pay race, refund clawbacks that survive webhook replays — and code that screams instead of lying.
The problem
A marketplace takes a driver's money and later pays the host — with cancellations, partial refunds, disputed charges, and Stripe webhooks that can arrive late, twice, or out of order in between. Money bugs are the worst kind: silent, compounding, and trust-destroying. Parkzy defers host payouts (hosts shouldn't have to clear full KYC before their first booking), which means the platform holds debts — and debts need a ledger, not a boolean.
The machinery
An IOU ledger, not a flag
Every deferred payout is a row: amount (checked positive), the payment intent it came from, the transfer that settles it, a settled-at stamp. A unique index per booking makes backfills idempotent, and row-level security allows no user writes at all — money rows are written only by service-role code.
Two-phase commit vs. the double-pay race
Phase 1 reserves the row by writing a placeholder transfer id, guarded on “transfer id is null, not settled, amount positive” — so two concurrent workers can't both claim it and a clawed-back row can't transfer. Phase 2 creates the Stripe transfer with a deterministic idempotency key. Phase 3 swaps in the real transfer id. Crash at any point and the retry reuses the same key — Stripe returns the original transfer instead of a second one.
Refund clawbacks that survive replays
When a refund lands out-of-band, the webhook atomically claims the clawback (a null-guarded stamp, so the webhook and the cancellation path can race and exactly one wins) and clamps the IOU to an absolute target — computed from what was refunded, not multiplied by a ratio — so Stripe redelivering the same webhook is a no-op instead of a double-clamp.
Scream, don't fabricate
If a transfer succeeds but the ledger update reports zero rows affected, the code refuses to count it as a settle: it logs “money moved with no ledger record” and demands manual reconciliation. The old code counted a fabricated success. The new code's comment says it plainly: if it ever happens, scream instead of lying.
Did it work?
An August 2026 audit reconciled every paid booking and cancellation directly against Stripe. After the fixes and backfills, a clean re-run reported zero dashboard-vs-Stripe mismatches on the pending set; 15 payouts totalling $803 settled within 48 hours of maturity; and of the IOUs still unsettled, every matured one was correctly unpayable (canceled booking, demo host, Connect not yet enabled). Honest caveat: that was a one-time audit, not yet a standing monitor — three reconciliation tools (charges, refunds, customers) run on demand, and a repeatable transfers-vs-dashboard report is on the backlog.
What I keep
Nothing here is exotic — it's the boring discipline applied everywhere at once: make illegal states unrepresentable, make every retry idempotent, make race winners explicit, and when reality and the ledger disagree, prefer the loud failure. Correctness with money isn't a feature; it's a posture.
The Pings Nobody Answered
A real marketplace diagnosis: 81% of dispatch offers were expiring untouched — $655 of demand in two weeks — and the root cause wasn't notifications. A case study in instrumenting before guessing.
The symptom
Parkzy's core loop is the ping: a driver taps once, every nearby host gets a 60-minute offer, first accept wins. Over one 21-day window, 21 requests went out, 17 expired untouched (81%) and exactly one was accepted. In the two weeks before the fix, $655 of offers died on the table — an average of $40.94 each. For an early marketplace, that's not a leak; that's the boat filling with water.
The investigation
Instinct said push notifications were failing. The data said otherwise: six of the eight hosts who let a ping expire were demonstrably inside the app during the 60-minute window. Meanwhile the event funnel showed only ~36% of recipient rows ever produced an in-app “ping received” event. Hosts weren't ignoring the offers — the product was hiding them.
Three root causes, none of them the obvious one
Dismissal was a no-op
Swiping away the ping sheet did nothing to the underlying offer — the row stayed pending and silently expired 60 minutes later. And once dismissed, the only ways back in were the notification bell or a push deep link.
A self-inflicted TTL bug
A fix from the week before set the push notification's APNs expiration to 300 seconds — for an offer that lives 60 minutes. Any phone offline for five minutes simply never received the push.
No standing surface
The driver's side had a persistent banner for the active request. The host's home screen — the side being asked to act — had none.
The fix
Three changes shipped together: a pending-ping banner on the host's home screen with a live countdown and the payout amount, one tap from anywhere back into the offer; dismissal copy that tells the host the offer is still live; and push TTL derived from the offer's actual expiry instead of a constant. The diagnosis and fix went from first data pull to production in the same week.
What the data says now
Two structural findings guide what's next. Speed compounds: pings accepted within five minutes go on to complete ~69% of the time, versus ~58% for slower accepts — every minute of visibility is worth real conversion. And dispatch is the next lever, not notifications: sixteen hosts who never accepted a single ping absorbed 56% of all offers ever sent, while two-thirds of active hosts had never been pinged at all. The lesson I keep: instrument the funnel before believing your own hypothesis — the obvious suspect was innocent, and the fix was product surface area, not infrastructure.
The Parkzy Ops Console
~78 internal pages, ~36,000 lines of TypeScript: the support and operations platform inside Parkzy — funnels, forensics, risk, disputes, a pricing lab, edge health — gated behind TOTP MFA. The unglamorous software that makes a marketplace operable.
Why it exists
A two-person company operating a live marketplace can't hire an ops team — it has to build one. Every recurring question became a page: Why did this ping die? Does the dashboard match Stripe? Which hosts are hurting the funnel? Is the edge healthy? The console is where a marketplace stops being a demo and starts being a business you can actually run.
Representative surfaces (of ~78)
Dispatch forensics
A sent→accepted→booked ping funnel, plus a per-ping forensic timeline that reconstructs exactly what each host saw and when — the tooling behind the ping-dispatch case study.
Money ops
Revenue, disputes with per-case detail, tax export, and the reconciliation tooling from the money-correctness work.
Risk & trust
Account risk, listing risk, behavioral signals, overstays and tows — the surfaces that keep a peer-to-peer marketplace safe to transact in.
Growth
Retention cohorts, attribution, unmet-demand mapping, SEO, host outreach and broadcast messaging.
Platform health
Feature flags, edge-function health, mobile bundle deploys, and a live AI-spend meter.
Pricing Lab
A shadow-mode sandbox for the ML pricing engine — compare the model's price against the live price on real inventory before letting it near production.
AI in the loop, humans on the trigger
Support runs AI-assisted, not AI-automated: edge functions triage inbound messages, draft suggested replies, and recommend dispute outcomes — an operator reviews and decides. The console is also where the 23-agent organization's output lands as concrete dashboards and queues.
The boring parts, done properly
The whole console sits behind TOTP multi-factor auth (step-up to AAL2 before any support surface renders), on top of row-level-security boundaries where user-facing roles can't touch money tables at all. Internal tools handle the most sensitive data in the company — they deserve production-grade security more than the marketing site does, not less.