Twenty days. Sixty-seven commits. One working product.
Blood went from “I need to understand my blood test” to v1.23.2 in three weeks. This post covers where we are, what’s next, what technical debt I’m carrying intentionally, and what success looks like six months from now.
Current State: v1.23.2
Code:
- 5,800 lines of code (frontend + backend)
- 67 commits
- 17 unit tests + regression tests + E2E tests
- 0 critical security vulnerabilities
Infrastructure:
- AWS eu-west-3 (Paris)
- CloudFront CDN (test + prod)
- Lambda (Python 3.12)
- S3 (frontend hosting + job state)
- API Gateway (throttled: burst 30, rate 10/s)
Costs:
- €22/month during development (includes testing overhead)
- Projected €30-50/month at 1,000 tests/month
- AI costs: ~€0.003 per test (Bedrock Nova 2 Lite)
Features Complete:
- PDF upload (drag-drop + click-to-browse)
- Password-protected PDF support
- AI analysis (extraction + outlier explanation + conclusion)
- Results visualization (range bars, donut charts, trend lines)
- IndexedDB storage (persistent across sessions)
- Test history (list, delete, navigate)
- Trends page (worsening/improving/stable classification)
- Manual entry mode (JSON paste or form)
- Privacy notice (full GDPR compliance)
- Consent banner (AI as recommended option)
- Feedback widget (Discord notifications)
- Mobile responsive (iOS Safari + Android Chrome tested)
- tinycount analytics (fire-and-forget, privacy-respecting)
The Backlog: What’s Next
Phase 1: Launch Readiness (June 2026)
| Item | Priority | Status |
|---|---|---|
| Deploy race fix | HIGH | [ ] Split HTML + asset sync into atomic operation |
| Rate limiting (WAF) | HIGH | [ ] AWS WAF rule: 100 req/5min per IP |
| Log retention enforcement | MEDIUM | [~] Need aws logs put-retention-policy per-env |
| Semantic version tag | MEDIUM | [ ] git tag v1.0.0 on main |
Phase 2: UX Polish (June-July 2026)
| Item | Priority | Status |
|---|---|---|
| BYOK flow redesign | MEDIUM | [~] File-optional, prompt-first experience |
| Canonicalize imported markers | MEDIUM | [ ] Ensure trends match for manual entries |
| Accessibility audit | LOW | [ ] WCAG 2.1 AA compliance |
| Dark mode | LOW | [ ] User preference toggle |
Phase 3: Growth Features (Q3 2026)
| Item | Priority | Status |
|---|---|---|
| Google Drive sync | HIGH | [ ] Cross-device storage (Phase 2) |
| Multi-language (NL/FR) | MEDIUM | [ ] Belgian market requirement |
| Compare mode | LOW | [ ] Side-by-side two tests |
| Health context profile | MEDIUM | [ ] Medications, conditions, goals |
| Next test planning | LOW | [ ] AI suggests markers to re-check |
Phase 4: Monetization (Q4 2026)
| Item | Priority | Status |
|---|---|---|
| Soft gate (3 free tests) | HIGH | [x] Counter implemented, not enforced |
| Payment integration | MEDIUM | [ ] Stripe or Paddle |
| Paid tier features | MEDIUM | [ ] Unlimited tests, cloud backup, trends export |
| B2B pricing | LOW | [ ] Whitelabel for labs |
Technical Debt Inventory
Some debt is intentional. Some is accidental. Here’s the list:
Intentional Debt (Will Refactor Later)
- Frontend state management: Currently using Svelte stores. Might migrate to runes-only pattern once Svelte 5 ecosystem matures.
- Test coverage: 17 backend tests, minimal frontend tests. Adequate for MVP, needs expansion before scale.
- Error messages: User-facing errors are generic (“Analysis failed”). Should be more specific without leaking implementation details.
Accidental Debt (Should Fix Soon)
- Deploy race condition: Two overlapping pipelines can leave
index.htmlpointing to deleted JS assets. Fix: merge HTML + asset sync into oneaws s3 synccall. - Log retention: CloudWatch log groups auto-created by Lambda can’t have retention set via CFN without import. Fix: run
aws logs put-retention-policy --retention-in-days 90per-environment. - Untracked benchmark scripts:
scripts/benchmark_*.pyfiles not committed. Either commit or delete.
Lessons Learned
What Went Well
- Constraints enabled speed: “Privacy by architecture” eliminated entire classes of decisions (no database design, no auth system).
- Async job pattern: Beat the 30-second API Gateway timeout cleanly. Reusable pattern for any slow AI workflow.
- Bedrock Nova 2 Lite: Right balance of cost, speed, and EU residency.
- Svelte 5: Small bundles, fast dev loop, no runtime bloat.
- GitLab CI/CD: Auto-deploy to test on every commit caught bugs early.
What I’d Do Differently
- Mobile testing earlier: Waited until users reported problems. Should’ve tested on real devices from day one.
- Progress indicator sooner: Infinite spinner was a known issue. Fixed it after first user complaint instead of anticipating it.
- Benchmark earlier: Almost shipped with nova_direct extraction. Would’ve caught the duplicate marker issue with earlier benchmarking.
- Log retention from start: Anonymized telemetry is clean, but should’ve set retention policy before first log written.
Success Criteria (6 Months Out)
December 2026 targets:
| Metric | Target | Current |
|---|---|---|
| Monthly active users | 1,000 | ~50 (beta) |
| Tests processed/month | 5,000 | ~200 (beta) |
| Error rate | <1% | 0.3% |
| p95 latency | <30s | 34s |
| Revenue | €5,000/month | €0 (free beta) |
| NPS | >40 | Not measured yet |
Qualitative goals:
- Users recommend Blood to friends unprompted
- At least one lab partnership inquiry
- DevLog series drives meaningful traffic to insightlab.be
- Zero security incidents or data breaches
The Philosophy Holds
Three principles guided every decision:
- Privacy by Architecture: No server-side storage. No accounts. No cookies. IndexedDB only.
- EU Data Residency: Everything in eu-west-3. AWS DPA for GDPR Art. 9 compliance.
- AI as Translator: Explains context, not prescriptions. Amplifies human judgment.
These weren’t constraints that slowed us down. They were the product.
What’s Next
Post-launch priorities:
- Rate limiting — Before any public sharing beyond closed beta
- Google Drive sync — Most requested feature (cross-device access)
- Multi-language — Dutch and French for Belgian market
- Payment integration — Freemium model: 3 free tests, then paid
And I’ll keep writing DevLogs. Next series might cover:
- Scaling to 10,000 users/month
- Internationalization patterns
- Payment integration without compromising privacy
- Lab partnership technical requirements
This is post #6 (final) in the Blood Development Log series. Read post #5 → | Series index →
Blood is built by DGTL bv. Privacy-first. EU-hosted. AI-powered.
🀄