Skip to main content

Test Plan: Drop — Fintech Payment App

Performance Test Plan: Drop — Fintech Payment App

Project: Drop — Remittance + QR Payments Version: 1.0 Date: 2026-02-23 Author: John (AI Director) Status: Approved Reviewers: Alem Bašić (CEO)

Document History

Version Date Author Changes
0.1 2026-02-23 John Initial performancetest plan — targetsall fromMVP NFR-P01..P06 + api-benchmarks.test.tsmodules

1. Performance TestingTest Objectives

This test plan covers testing for Drop MVP + Phase 0.5 Security Hardening (v0.5.0).

Primary objectives:

  1. Verify that all authentication and onboarding flows (registration, OTP, PIN, login) work correctly for Norwegian residents (age ≥ 18, phone +47)
  2. Verify that remittance transactions apply correct 0.5% fee across all 6 NOK corridors with mock BaaS
  3. Verify that QR payments apply correct 1% merchant fee with mock BaaS
  4. Confirm the pass-through model invariant: Drop NEVER stores user balances or full card data
  5. Confirm Phase 0.5 security hardening: bcrypt 12 rounds, persistent rate limiting, CSRF, security headers, audit logging
  6. Validate that Drop meets the performance SLAs defined in the NFR document under normalexpected operating conditionsload (20040+ concurrent usersusers; ontarget SQLite200 MVP; 5,000+ on PostgreSQLfor Phase 1)
  7. Determine the SQLite concurrent user limit before migrating to PostgreSQL (target: migrate at 200 concurrent)
  8. Identify bottlenecks (bcrypt hashing, DB queries, rate limiter) before production release
  9. Establish a performance baseline for regression comparison in future releases

ReferenceOut NFRs:of scope for this plan: docs/BUSINESS-REQUIREMENTS/non-functional-requirements.mdBankID — Section 2SCA (Performance)Phase 2), real BaaS payments (Phase 2), real Sumsub KYC (Phase 2), Cards feature (Phase 3), mobile native app (Phase 2).


2. PerformanceFeatures RequirementsUnder ReferenceTest

+ + + + + + + + Builder+ +
EndpointFeature / FeatureStory P50Priority P90Test Types P95P99Error RateNotesOwner
GETUser /api/healthRegistration — 3-step (FR-001) < 20msCritical <Unit, 50msIntegration, E2E <Builder 100ms < 200ms< 0.1%Health check — fast alwaysValidator
POSTUser /api/auth/loginLogin (bcrypt)FR-002) < 700msCritical <Unit, 900msIntegration, E2E <Builder 1,000ms < 1,200ms< 0.1%bcrypt 12 rounds; NFR-P03Validator
POSTRemittance /api/auth/registerTransaction (bcrypt)FR-020) < 700msCritical <Unit, 900msIntegration, E2E <Builder 1,000ms < 1,200ms< 0.1%Same bcrypt costValidator
POSTExchange /api/transactions/remittanceRates API (FR-021) < 200msHigh < 350msIntegration <Builder 500ms < 800ms< 0.1%NFR-P02Validator
POSTQR /api/transactions/qr-paymentPayment — Consumer (FR-030) < 200msCritical <Unit, 350msIntegration, E2E <Builder 500ms < 800ms< 0.1%NFR-P02Validator
GETMerchant /api/ratesRegistration + QR (FR-031) < 20msHigh <Unit, 50msIntegration <Builder 100ms < 200ms< 0.1%Cached / fastValidator
GETRate /api/transactionsLimiting (NFR-SEC05) < 50msCritical < 100msIntegration <Builder 200ms+ Validator
Input Validation / Security (NFR-SEC06) < 400msCritical <Unit, 0.1%E2E (input-chaos) NFR-P02Builder + Validator
DB SELECTCompliance query— No Balance/CVV (NF-AC-020/021) Critical Integration (db.test.ts) <Builder 10ms 0%NFR-P04Validator
DBbcrypt INSERTHashing query(NFR-SEC02) Critical Unit (auth.test.ts) <Builder 20ms 0%NFR-P04Validator
50Performance concurrentBenchmarks rate limit checks(NFR-P01..P06) High Performance (api-benchmarks) 0%< 2,000ms total (NFR-P06)Validator
PageFeature loadFlags (First Contentful Paint)FR-090) Medium Unit (feature-flags.test.ts) <Builder 3,000ms NFR-P01 (4G, cold cache)
Core Web Vitals LCP< 2,500msNFR-P05Validator

3. Test TypesScope

3.1In Load Testing — Normal Load SimulationScope

Objective:

    Confirm
  • Authentication Dropmodule: meetsregistration, SLAsOTP underverification, expectedPIN normalsetup, loadlogin, logout, /api/auth/me
  • Remittance module: POST /api/transactions/remittance, GET /api/transactions, exchange rates
  • QR payments module: POST /api/transactions/qr-payment, POST /api/merchants, GET /api/merchants/me
  • Security middleware: rate limiting, CSRF, JWT validation, security headers
  • Database compliance: schema assertions (Norwegianno remittancebalance, corridorno peakcard_number, traffic)no Normalcvv), loadFK definition:constraints, 200transaction type enum
  • Performance benchmarks: bcrypt timing, DB query latency, concurrent users (SQLite MVP limit) / ~20 requests/second Duration: 10 minutes (after 2-minute ramp-up) Pass criteria: All SLA targets in Section 2 met with ≤ 0.1% error rate

    3.2 Stress Testing — Beyond Normal Capacity

    Objective: Find SQLite concurrent user limit; understand failure behavior to plan PostgreSQL migration Starting point: 50 users, increasing by 25 users every 2 minutes Stop condition: Error rate >limit 5%check orthroughput

  • P99
  • Regression > 3,000ms or service crashes Pass criteria: System fails gracefully with meaningful error messages (429 rate limit, not 500); data integrity maintained; no double-spend under stress

    3.3 Spike Testing — Sudden Traffic Surges

    Objective: Simulate scenarios like marketing campaigns or media coverage causing sudden user influx Baseline: 20 users Spike to: 100 users (5× baseline) Spike duration: 2 minutes Pass criteria: System recovers to baseline performance within 5 minutes after spike ends; no data corruption

    3.4 Endurance / Soak Testing — Sustained Load

    Objective: Identify SQLite file lock issues, connection pool exhaustion, memory leaks under sustained load Load level: 50 users (25%testing of 200all concurrent26 limit)API Duration:routes

  • 2
  • Input hoursvalidation: MetricsXSS, toSQL watch:injection, SQLiteboundary writeages, queueUnicode depth,names, memorylong usagepasswords
  • trend, response time trend Pass criteria: No upward trend in response time over soak period; no SQLite database locked errors

3.5Out Scalabilityof Testing — Phase 1 PostgreSQL MigrationScope

Objective: Verify PostgreSQL migration enables proportional scaling for Phase 1 target (5,000+ users) Test: Step load from 200 to 1,000 concurrent users on PostgreSQL staging Pass criteria: P95 stays under 500ms as concurrent users scale; no P99 explosion Note: PostgreSQL not yet deployed — Phase 1 task. This plan establishes the baseline for comparison.


4. Load Profiles

PhasePhase1 PostgreSQL
ScenarioItem Virtual UsersRamp-UpHoldRamp-DownThink TimeNotesJustification
SmokeBankID (quickSCA sanity)integration 5Phase 2 — not yet implemented
Real BaaS PISP/AISP payments 10sPhase 2 — mock mode only in MVP
Real Sumsub KYC webhooks 1minPhase 2 — auto-approved in MVP
Cards feature 10sPhase 3 — feature-flagged OFF
Mobile native app 1s Per-deploy2 quick checkweb only in MVP
Load (normaltesting SQLite)> 200 concurrent users 200 2min 10min1min2sNFR-S01 MVP target
Stress (find limit)Upmigration to 500 2minrequired stepsUntil fail2sSQLite vs PostgreSQL
Spike (traffic burst)100 (instant)0s2min0s1sMarketing/media event
Soak (stability)501min2h2min3sMemory leak detectionfirst

Think time simulation: Realistic user think time of 2–5s (Norwegian users reviewing remittance details before confirming)


5.4. Test EnvironmentSchedule & Milestones

NOTE: Performance tests run against a representative staging environment. SQLite MVP limits are tested on Fly.io staging (1× shared CPU, 256MB RAM). Phase 1 PostgreSQL tests require production-equivalent environment.

ComponentMilestone MVP Staging (Fly.io)Date Phase 1 TargetResponsible
AppTest instancesplan approved 1× shared-cpu-1x (256MB)2026-02-23 John dedicated-cpu-2x(AI Director)
DatabaseTest environment ready (staging) SQLiteBefore onPhase persistent0.5 volumerelease PostgreSQLJohn (managed Fly.io)DevOps)
RegionTest data seeded StockholmBefore (arn)E2E run StockholmBuilder (arn)agent
CDNUnit + integration tests complete NonePer PR (APICI automated)Builder agent
Playwright E2E authoring completeBefore Phase 0.5 releaseBuilder agent
Regression testing complete (all 26 routes)Before Phase 0.5 releaseValidator agent
Performance benchmarks runBefore Phase 0.5 releaseBuilder agent
UAT start (CEO walkthrough)TBD — before Phase 1 launchJohn
UAT sign-offTBDAlem Bašić (CEO)
Go/no-go decisionBefore Phase 1 launchAlem Bašić (CEO)
Production releasePhase 1 (BaaS partner confirmed)John (AI Director)

5. Resource Allocation

ResourceRoleTesting ActivitiesAvailability
Builder Agent (Claude Sonnet)Developer / QAUnit + integration + E2E authoringPer task
Validator Agent (Claude Sonnet, read-only) NoneQA LeadCode review + test verificationPer task
John (API)AI Director)Tech LeadTest strategy, UAT coordinationContinuous
Alem Bašić (CEO)Product Owner / VercelUATCEO UAT walkthroughTBD

6. Entry Criteria

Testing may begin when:

  •  Feature development is code-complete (landing)all tickets in "Ready for QA")
  •  Unit tests passing (≥ 100% pass rate on unit + integration suite)
  •  Build artifact deployed to staging (https://drop-staging.fly.dev/)
  •  Staging environment is stable (health checks passing)
  •  Test data is seeded (npm run db:seed)
  •  Previous known blocking bugs resolved (Mission Control backlog reviewed)

7. Exit Criteria

Testing is complete when:

  •  All 14 test files execute cleanly
  •  ≥ 100% of unit + integration tests pass
  •  All Critical and High test cases in AC-001–AC-092 pass
  •  Code coverage ≥ 80% overall; 100% for auth + transaction paths
  •  All Playwright E2E tests passing on staging (user-flows, full-flows, input-chaos)
  •  Performance benchmarks meeting NFR-P01..P06 targets (api-benchmarks.test.ts green)
  •  DB compliance tests passing (db.test.ts: no balance, no card_number/cvv columns)
  •  UAT sign-off obtained from Alem Bašić (CEO) — or conditional approval documented
  •  Security audit score ≥ 80/100 (post Phase 0.5 hardening)

Exceptional circumstances: If exit criteria cannot be met, a documented risk acceptance from Alem Bašić (CEO) is required.


8. Test Strategy Summary Per Type

TypeApproachToolOwnerGate
UnitWhite-box — bcrypt, JWT, fee calc, validatorsVitestBuilderBlocks merge
IntegrationReal SQLite test DB — 26 API routes, DB schemaVitestBuilderBlocks merge
E2ECritical journeys on staging — 3 Playwright projectsPlaywrightBuilderBlocks release
RegressionAll 26 routes via api-endpoints.test.tsVitestBuilderBlocks merge
Performanceapi-benchmarks.test.ts — bcrypt timing, query latencyVitest benchBuilderWarning → release
Securitynpm audit + validation.test.ts + middleware.test.tsVitest + GitHub ActionsBuilderBlocks merge
DB compliancedb.test.ts — schema assertionsVitestBuilderBlocks merge
UATCEO business scenario walkthroughManualAlem BašićBlocks Phase 1 launch

9. Test Environment Requirements

EnvironmentPurposeURLAccess Needed
Local devUnit/integrationhttp://localhost:3000Builder agent
Staging (Fly.io, Stockholm)E2E, regression, UAThttps://drop-staging.fly.dev/Team + Alem
PerformanceBenchmarksLocal (api-benchmarks.test.ts)Builder agent

LoadEnvironment generator:requirements:

  • Tool:Staging Vitestmust benchmarkshave NEXT_PUBLIC_SERVICE_MODE=mock (api-benchmarks.test.ts)no forreal micro-benchmarksBaaS)
  • LoadStaging generatorSQLite forDB integration:seeded k6with scriptssynthetic intest infrastructure/performance/data (no real PII)
  • LoadMonitoring generator location: Local or CI runnerenabled (same region as Fly.io Stockholm)metrics)

6.10. Test Data Requirements

Data TypeCategory Volume GenerationCreation MethodResponsible
UsersTest consumer accounts 5003 (fresh, KYC-approved, KYC-pending) npm run db:seed:perfseedBuilder agent
RecipientsTest (remittancemerchant targets)accounts 2002 (registered, unregistered) Seednpm scriptrun db:seedBuilder agent
MerchantsTest recipients (for remittance) 503 Seednpm scriptrun db:seedBuilder agent
TransactionsEdge case data (historical)under-18, duplicate email, max amounts) 10,000Defined per test BulkVitest insert seed
Exchange ratesfixtures 6Builder corridors (fixed)Always seededagent

DatabaseData sizecleanup: atAll test time:data ~50MBremoved SQLiteafter file Data preparation: npmtest run db:seed:perfvia Vitest afterEach (estimatedteardown. time:Staging ~2DB minutes)reset between major test runs.


7.11. ToolsRisk-Based &Test InfrastructurePrioritization

dashboard
ToolRisk Area VersionLikelihood PurposeImpact ConfigPriorityMitigation
VitestPass-through model violation (bench)Drop stores balance) 2.xLow Micro-benchmarks: bcrypt, DB queries, rate limiterCritical src/drop-app/__tests__/api-benchmarks.P1db.test.ts always asserts no balance column
k6Authentication bypass LatestLow HTTP load testing (concurrent users)Critical infrastructure/performance/k6-scripts/P1Full auth.test.ts suite + middleware.test.ts
Fly.ioFee Metricscalculation error (wrong percentage) Medium Real-time CPU/memory/request metricsCritical Fly.ioP1 Unit tests for 0.5% and 1% fee calculations
Double-spend race conditionLowCriticalP1Transaction lock integration test
Rate limiter reset on server restartMedium (was a bug)HighP2middleware.test.ts with persistent limiter
BaaS mock mode leaking to production configLowHighP2CI check for NEXT_PUBLIC_SERVICE_MODE env var
SQLite EXPLAINconcurrent QUERYwrite PLANlimit reached High (at ~200 users) DB query analysisMedium Via flyctl ssh console

Script location: src/drop-app/__tests__/api-benchmarks.test.ts (Vitest benchmarks)


8. Key Metrics to Capture

Response Time

MetricDescriptionTool
P50 (median)P3 Half of requests faster than thisVitest bench / k6
P9090% of requests faster than thisk6
P9595% of requests faster than thisk6 (NFR gate)
P9999% of requests faster than thisk6
MaxWorst single requestk6

Throughput

MetricDescription
Requests/secondTotal API throughput at peak load
Transactions/secondSuccessful remittance/QR transactions per second

Error Metrics

MetricTarget
HTTP error rate (5xx)< 0.1%
SQLite database locked errors0% (rate limit blocks excess concurrency)
Connection timeout rate< 0.1%

Resource Utilization (Fly.io Metrics)

ResourceWarningCritical
App CPU> 70%> 90%
App Memory> 80% (200MB / 256MB)> 95%
SQLite write queue> 50ms wait> 200ms wait

Database Query Performance (NFR-P04)

MetricTarget
SELECT query P95< 10ms
INSERT query P95< 20ms
Slow queries (> 100ms)0 per minute under normal load

9. SLA Targets Per Endpoint (from api-benchmarks.test.ts)

EndpointMethodP95 SLAError Rate SLANotes
/api/auth/loginPOST1,000ms< 0.1%bcrypt 12 rounds
/api/auth/registerPOST1,000ms< 0.1%bcrypt 12 rounds
/api/transactions/remittancePOST500ms< 0.1%NFR-P02
/api/transactions/qr-paymentPOST500ms< 0.1%NFR-P02
/api/ratesGET100ms< 0.1%Cached
/api/healthGET100ms< 0.1%Always fast
DB SELECT10ms0%NFR-P04
DB INSERT20ms0%NFR-P04
50 concurrent rate limit2,000ms total0%NFR-P06

10. Baseline Establishment (api-benchmarks.test.ts Results)

Baseline established: Phase 0 MVP on local dev (SQLite in-memory)

MetricBaseline ValueDate RecordedTest
bcrypt hash (register)~800ms2026-02-23api-benchmarks.test.ts
bcrypt verify (login)~800ms2026-02-23api-benchmarks.test.ts
Rate limit check (50 concurrent)~1,800ms2026-02-23api-benchmarks.test.ts
DB SELECT~5ms2026-02-23api-benchmarks.test.ts
DB INSERT~10ms2026-02-23api-benchmarks.test.ts
SHA-256 hash (reject baseline)~1ms2026-02-23auth.test.ts

Regression threshold: Alert if any metric degrades > 15% vs baseline


11. Test Execution Schedule

Run TypeTriggerEnvironmentFrequency
Benchmark smokeEvery CI runLocal / CI runnerPer commit
api-benchmarks.test.ts fullEvery PRCIPer PR
k6 load testRelease candidateFly.io stagingPer release
k6 stress testBefore Phase 11: PostgreSQL migrationFly.io stagingQuarterly
k6 soak testBefore Phase 1 launchFly.io stagingPre-launch

12. ResultsDependencies Analysis& TemplateAssumptions

TestDependencies:

Run
    ID:
  • Staging environment provisioned and accessible at https://drop-staging.fly.dev/
  • Mock BaaS and Mock Sumsub configured in staging environment variables
  • Playwright installed in CI (npx playwright install)

Assumptions:

{RUN_ID}
    Date:
  • Feature {DATE}requirements Tester:will not change during the testing phase without John (AI Director) review
  • All Builder Agentagent PRs include tests alongside code
  • Validator agent reviews test files before merge
  • BaaS partnership not confirmed — mock mode accepted for MVP/staging

13. Defect Management Process

Bug tracker: Mission Control tasks + ValidatorSlack Agent#drop-bugs on alai-talk.slack.com Scenario:Severity levels: Load (normal) / Stress / Spike / Soak Build / Version: v{VERSION}

no Fixbefore
EndpointSeverity P50 (ms)Definition P90 (ms)P95 (ms)P99 (ms)Error %RPSStatus vsResolution SLA
/api/auth/loginCritical Financial invariant broken; auth bypass; data loss Fix before release Pass / Failexceptions
/api/transactions/remittanceHigh Major feature broken; security finding; no workaround Pass / Failrelease
DB SELECTMedium Feature degraded; mock/workaround exists Fix in next sprint
Low Minor issue, cosmetic Pass / FailBacklog

Summary:Bug lifecycle:

    Open
  • Peak concurrent users: {PEAK_USERS}
  • Peak throughput: {PEAK_RPS} req/s
  • Test duration: {DURATION} min
  • Total requests: {TOTAL_REQUESTS}
  • Total errors: {TOTAL_ERRORS}

Notable findings:

  • SQLite concurrent user limit reached at: {LIMIT} users
  • Recommend PostgreSQL migration at: {TRIGGER} concurrent usersAssigned (perMission NFR-S02)
  • Control)

In Progress → Fixed → Verified by Validator → Closed Recommendation:Triage cadence: PassOn /each FailPR/commit /(CI-driven); Conditional pass with PostgreSQL migration requireddaily for Phaseactive 1test phase


13. Bottleneck Identification Process

Drop-specific bottleneck investigation order:

1. Check bcrypt timing → bcrypt > 1,000ms P95 = config issue (rounds too high OR long password pre-check missing)
2. Check SQLite write queue → "database is locked" errors = concurrent write saturation → trigger PostgreSQL migration
3. Check rate limiter DB table → rate_limit_requests table query slow = add index or migrate to Redis
4. Check transaction lock → SELECT FOR UPDATE timeout = deadlock in double-spend prevention
5. Check mock BaaS response → mock service timeout = CI/staging environment issue
6. Check Fly.io metrics → CPU > 90% = scale up instance; Memory > 200MB = Node.js leak check

14. RemediationTest TrackingDeliverables

maxlengthbefore
IssueDeliverable Found InFormat SeverityDue Date Root CauseFixFixed InVerifiedOwner
In-memoryTest rateplan limiter(this reset on restartdocument) Phase 0 load testMarkdown High2026-02-23 In-memoryJohn Map(AI → DB-backedPhase 0.5 security hardeningv0.5.0db.test.tsDirector)
LongTest password bcrypt DoS (10KB)strategy Phase 0 security audittest-strategy.md High2026-02-23 NoJohn
Test bcryptcases (automated) 1,000Vitest char+ limitPlaywright intest validationfiles v0.5.0Per sprint validation.Builder agent
Test execution resultsVitest + Playwright CI reportsPer PRCI
Performance test reportapi-benchmarks.test.ts outputPer releaseBuilder agent
UAT sign-offuat-signoff.mdBefore Phase 1Alem Bašić
Test summary reportMarkdown (per release)Per releaseValidator agent


Approval

Role Name Date Signature
Author John (AI Director) 2026-02-23 Approved (AI)
QA Lead Validator Agent 2026-02-23 Approved (AI)
AI Director (John) John 2026-02-23 Approved
CEO (Alem) Alem Bašić TBD