VP Product for two years, then back as a hands-on builder: store releases, server-side payments, pricing for 250 countries, security and infrastructure, all written in the codebase with Claude Code.
Sana ArshadIslamabad, Pakistan · remote with Canadian teamsLinkedIn
What this page shows
Seven pieces of work on Ayuda Health: Pill Reminder, a medication-reminder and vitals app, each backed by the repositories, store consoles and release notes.
A Flutter release train to the App Store and Google Play, with a rebrand and a policy rejection turned around in a day.
12App Store Connect uploads and 2 Play releases in 25 days for version 3.4.x
250countries priced in 128 currencies, live without an app update
92/92end-to-end checks passed after moving Stripe behind the backend
7production security fixes deployed in one day, then HTTPS on a real hostname
~37%of monthly AWS spend removed, with snapshots taken first
Every figure on this page traces to a commit, a build number, a store console or a release note. Infrastructure identifiers and still-open security items are left out.
The work
Ayuda Health
A medication-reminder and vitals app used by hundreds of thousands of people. I was VP Product for two years, then returned as a hands-on builder: releases, payments, pricing, security and infrastructure, working directly in the Flutter and Node codebases with Claude Code.
VP Product · 2 years Hands-on build engagement
Commit-level evidence: every claim in this chapter comes from the repositories, store consoles and release notes of the engagement. Infrastructure identifiers and still-open security items are deliberately left out.
FeaturedMobile · Flutter release engineering
Ayuda Health: Pill Reminder, the 3.4.x release train
From a Mac with no toolchain to a dozen App Store Connect uploads and a dual-store launch in under four weeks, including a rebrand and a Play policy rejection turned around the same evening.
Store screenshot: medication management.Store screenshot: device connections.Store screenshot: eDiary and vitals.Regenerated eDiary shot, verified by pixel diff.
Play Console, bundle 110 (3.4.1): 17,235 supported devices, 158 localizations.The Health Connect rejection, answered in writing and resubmitted that evening.
The Flutter app, 442 Dart files, had no working build environment and a stale main branch. Within a day the toolchain was bootstrapped without admin rights, the real release branch found, and a hard-coded version stamp in the Xcode project fixed after it caused duplicate-upload rejections. Version 3.4.1 went to both stores with health sync, Apple Health branding, a production environment switch and the "Ayuda Health: Pill Reminder" listing rebrand.
Google Play's Health Connect rejection was root-caused and a corrected build resubmitted the same evening at a staged rollout. 3.4.2 added the Android 16 target and a region-aware paywall and went live on iOS; 3.4.3 was held on TestFlight under a new rule: nothing is submitted without explicit sign-off.
Headless iOS pipeline: config-only Flutter build, xcodebuild archive and export with cloud signing, altool upload, and a watcher on the App Store Connect API that answers export compliance. Twelve uploads in 25 days.
Release commit for 3.4.1: minimal read-only health permission sets, 24-hour eDiary auto-sync, Apple Health branding in 10 languages, and the backend URL bound to the build type so a production build can never point at staging. 14 of 14 tests.
Store rebrand: paste-ready App Store and Play listings, screenshots regenerated and verified by pixel diff, a six-hour hung upload diagnosed and re-run in five minutes.
Play rejection handled in writing: 11 per-permission justifications in the Health apps declaration; build 113 approved at a 20% staged rollout.
Android build modernised: Android Gradle Plugin 8.11.1, Kotlin 2.2.20, Gradle 8.14.3 and targetSdk 36 ahead of Google's deadline.
Startup crash fixed before release: a raw JSON column with four live shapes crashed the app for over half of staging users; a tolerant parser with six regression tests and a contract test against live staging closed it.
Tester distribution: per-ABI APKs, a local download server with a QR code, and a Samsung sideload blocker root-caused for the owner's test phones.
Mobile · Apple Health & Health Connect
Wearable integration overhaul
A read-only, feature-justified health-data pipeline that works on real iPhones and syncs the eDiary every day.
Apple Health connect screen, rebranded and redrawn.Health Connect on Android: read-only, 11 types.The connect screen once a device is linked.
The Health Connect flow re-prompted on every screen, requested roughly 68 Android permissions while the manifest declared 6, and every HealthKit call failed on real iPhones. The permission set was cut to a read-only list mapped to visible features, a previous store-rejection cause removed, and every read isolated per type so one failure cannot blank the dashboard. A 24-hour auto-sync was built on both platforms with catch-up on open and instant sync on connect; sleep goals auto-complete from wearable sleep behind a consent popup; an HRV tile was added; and iOS was rebranded "Apple Health" across 10 languages.
Root causes: six views fired authorization on mount, and a nutrition meta-type registered about 40 write-only types that aborted HealthKit's batched query.
iOS background sync could never have run before: the background task identifier, fetch mode and launch handler were all missing. The permission sheet went from about 50 rows to 12 with zero read errors in verification.
Never silently log: the sleep auto-track replaced a fake spinner with the real permission flow and a confirmation when the recorded value contradicts the goal.
Disconnect revokes access instead of opening a settings page; "No wearable data found" probes the last seven days; "Add readings" prefills BP, glucose, heart rate, respiratory rate and weight.
Lesson captured in code: every Health Connect type needs a matching store declaration, or updates get rejected.
FeaturedBackend · Payments
Server-side Stripe payments
Moved a live Stripe secret out of a shipped mobile binary and behind a contract-faithful Express API, with the app swap reduced to a single file.
The app called Stripe directly from phones with a secret key inside the binary. Six payment endpoints were built first as a standalone TypeScript module with a 15-test suite, then ported into the backend following its conventions, with response shapes preserved so the app change was one repository file. The Stripe SDK was pinned to the API version the app's generated models expect.
A 30-agent adversarial review confirmed 12 findings, five fixed in code and re-verified. 92 of 92 end-to-end checks passed against real Stripe test mode, the first secret-free purchase completed on an emulator, and the swap shipped in 3.4.1. Production was unblocked by a supervised deploy after the auto-deploy runner was found dead.
Deleted the unauthenticated payment-intent endpoint on purpose: no callers in the app, and a card-testing primitive.
Deploy forensics: found that any pull request against the live branch restarted production, and verified a safe integration branch that triggers nothing.
Staging deploy through EC2 Instance Connect with a throwaway key and a temporary firewall rule, both revoked afterwards.
Fixed a lapsed-subscription crash that silently downgraded paying-then-lapsed users.
The live key never crossed chat: it was placed on the server through a silent prompt over SSH.
Shipped alongside: free-trial status in Settings and a once-per-day upgrade reminder.
FeaturedBackend · Pricing & billing
Regional pricing by IP and local-currency billing
A 28-row pricing document became a 250-country, 128-currency Stripe pricing engine that went live without an app update.
Country
Tier basis
Monthly
Yearly
United States
USD reference tier
$3.99
$29.99
United Kingdom
Local currency, charm-rounded
£0.99
£9.69
Brazil
Local currency, charm-rounded
R$4.09
R$40.99
India
Raised to Stripe's minimum
₹49
₹476
Pakistan
Whole-unit currency, no decimals
Rs 139
Rs 1,389
The CEO's per-country pricing document was audited against the app, the backend and the live Stripe account: users had no country field, the backend served the first USD price to everyone, and existing subscribers had to be protected. A 25-tier map covers all 249 ISO country codes plus Kosovo with fallback countries flagged for review, IP-based detection ignores spoofed forwarding headers, and 50 Stripe prices were created under lookup keys by an idempotent, dry-run-first sync tool. Phase one went live first, so the already-shipped app showed regional prices immediately.
When "local pricing" turned out to mean local currencies, currency options were attached for 128 currencies at FX-derived, charm-rounded amounts, a Stripe-minimum bug that let sub-floor plans activate for free was fixed, and the app gained a region-aware paywall and correct currency signs.
Decisions made and recorded: existing subscribers grandfathered; country from IP rather than signup choice or GPS; sanctioned regions keep free features behind a "not available in your region" paid screen; stale prices archived without touching subscribers.
Verified live by country after each deploy; a price ID from another region returns 400.
Sync tool invariants: never archive a price with subscribers, never touch the default price, redact keys in logs, a five-second abort countdown before writes.
"Brazilian prices in Pakistan" diagnosed from server logs as a VPN exit, and the decision to keep pure IP pricing.
App side: tolerant region parsing so old servers stay billable, a 136-entry currency-symbol map with CLDR spacing, whole-unit currencies without decimals, a 73-currency render test.
5,156 self-check assertions on the tier and currency map, run from one script.
Backend · Security
Backend security hardening and HTTPS
Seven production auth fixes in a day, a self-inflicted login outage owned and hot-fixed within the hour, then TLS on a real hostname.
An independent four-reviewer end-to-end review passed 13 of 13 requirements and also surfaced credential leaks on unauthenticated endpoints of the live API. They were closed in a single day along with stack-trace leaks, per-IP and per-email rate limiting, bcrypt password hashing with transparent migration on login, and an OTP-gated password reset. Stripping fields that shipped apps still parsed broke every login; the hotfix restored the contract within the hour while keeping the leaks closed. The API then moved from a raw IP address to https://api.ayudahealth.com with a Let's Encrypt certificate and TLS 1.2 and 1.3 only, with the old address kept alive for installed builds.
Rate limits per 15-minute window on OTP send, OTP verify and password change, both per IP and per email.
bcrypt migration verified live: a legacy user logs in and is upgraded to a hash, logs in again, and a wrong password is rejected.
Lesson recorded in the repo: never change the shape of a response the shipped apps parse without reading the mobile model first.
Data-loss bug found from production records: completed reminder logs were stored empty because the server read one field while apps sent another. Fixed and deployed.
HTTPS: certbot on nginx, one DNS record set with the owner, a watcher polling the record, renewal dry-run passed twice.
Infrastructure · AWS
AWS cost audit, cleanup and lockdown
A line-item audit, about 37% of monthly spend removed with snapshots first, and an evidence-based database lockdown after a rollback.
The monthly bill was reconciled to the cent across three regions with Cost Explorer at usage-type level and 14 days of CloudWatch metrics per resource. An unnamed Windows server at 0.4% CPU was 29% of the bill, an RDS Proxy had zero connections for its entire life, and the dev database had shown no connections for 14 days. Verification before cutting reclassified two "idle" servers as live APIs. With the owner's go-ahead the Windows box was snapshotted and stopped, and the proxy and dev database deleted behind final snapshots.
A same-day firewall tightening cut off connections the wide-open rule had hidden. It was rolled back three minutes after the report, and the lockdown was redone using VPC Flow Logs, which proved which server was the real production backend.
55 to 65% of spend was found to be doing nothing.
Hardening: world-open database rules removed, SSH restricted to the owner, stop and terminate protection on production, backup retention raised from 1 to 7 days, a budget alarm set.
Flow-log capture: 649 connections in 11 minutes, 599 from production; explicit allow rules for every source seen; two port scanners now get silence.
The outage was owned in plain language and recovery watched live as connections returned.
Support-plan downgrade deferred to the CEO with a costed comparison rather than decided unilaterally.
Product analysis · Localization
Product roadmap analysis and 10-language translation drafts
Three product questions answered with code evidence and branded mockups, then 931 app strings drafted into ten new languages with independent review.
The owner asked which languages to add without growing the app, how to remind free users without hurting retention or store compliance, and how to bring wearable activity and calories into goals. A 14-agent analysis with readers, competing proposals, policy-checking judges and a critic found that the ten existing language files add only about 0.18 MB compressed, that the "trial ended" popup fired on every launch forever, and a zero-new-permission design for an energy loop. It published Ayuda-branded mockups built from the app's real design tokens.
With automatic translation chosen, all 931 strings were drafted into eleven languages with one translator and one independent reviewer per language, placeholder integrity checks and clinical back-translation. Ten language files were written for the next release; Traditional Chinese was held for a further review.
Languages in three waves: Indonesian, Turkish, Vietnamese, Polish, Ukrainian; then Japanese, Korean and Traditional Chinese once the report PDF has fonts; then Thai, Bengali and Malay.
Real blocker found: the doctor-report PDF cannot print Arabic, Urdu or Hindi names with its current font.
Subscription reminders: capped dialogs, a dismissible banner and opt-in local notifications; in-app Stripe flagged against App Store rule 3.1.1.
Indonesian example: 366 clinical strings back-translated and the standard pharmacy term for directions adopted.
Practice
How I work
One person in the codebase, with Claude Code as the build partner. The habits below show up in every entry above.
Evidence before opinion
Store screenshots verified by pixel diff, the database lockdown redone on flow-log evidence, and a tolerant parser proven with a contract test against live staging before release.
Adversarial review at scale
Multi-agent reviews attack the work before it ships: 30 agents on the Stripe module, 13 on the goals layout, 14 on the product analysis, and four independent reviewers on the end-to-end release check.
Ship safely, then say so
Snapshots before deletions, dry runs before Stripe writes, TestFlight before every submission, and an explicit "submit it" before anything goes to a store. When something breaks, the outage is owned in plain language and fixed within the hour.
Backward compatible by default
Response shapes preserved so the payments swap was a one-file change; tolerant region parsing so old servers stay billable; the raw-IP address kept alive for installed builds while HTTPS went live.
Capabilities
Skills, as demonstrated above
Product leadership
Roadmaps, PRDs and specs engineers build from
Competitive research synthesis and design guardrails
Owner decisions captured and turned into runbooks
Store policy and compliance: App Store 2.3.10 and 3.1.1, Play Health Connect
10+ years across healthtech, eCommerce and fintech: shipping patient apps, optimising funnels and checkout through A/B tests, and running the analytics that decide what to fix. A mechatronics engineering education still shapes how I debug.
5.5 years · Canada, remote
Your Doctors Online · Head of Product
Joined as Senior PM, moved through Growth PM to Head of Product. Built the patient apps from scratch, owned the funnel end to end and took payment conversion from 5% to 15% through A/B tests driven by funnel data, heatmaps and session recordings; scaled revenue from zero to seven figures while keeping US and Canadian healthcare compliance intact.
2 years · Canada
Ayuda Health · Vice President of Product
Owned strategy and roadmap for an AI-assisted medication reminder app, balancing AI features with regulatory compliance; later returned to build hands-on.
2 years · USA
Gemnote · Senior Product Manager
Directed eCommerce and branded-merchandise product development for B2B and B2C, delivering revenue features for clients including Google, Reddit and Amazon. See the Gemnote portfolio →
1 year · UK
Marketplug · Product Manager
Contributed to a multi-vertical super app spanning chat, crypto and eCommerce across 30-plus niches.
Contract engagements
Sidq Capital · BlockMed Pro · Digital Twin platform
FCA-regulated fractional property investment MVP (payments, wallet, KYC and e-signature vendor decisions); a GDPR-compliant patient health-data marketplace with blockchain-anchored consent; a pharma digital-twin simulation platform scoped from vision to MVP.
Education
Mechatronics Engineering, Air University
PhD in progress; MS with gold medal; BS. Certifications in generative AI for product managers, agile project management and Scrum, plus the Acquisition.com Scaling Workshop in the US.