Amber

State of the Costco Android App

An amber health status overall. Architecture, build modernity, and DI are strong. Stability, accessibility, and modernization carry material risk that needs two focused quarters of investment to bring to industry parity.

Costco Android v26.4.1.2 · 1 app + 22 features + 30 shared + 3 core/lib · 626 concrete findings · Reviewed 2026-05-07
67
HEALTH

Headline indicators

Overall health
67/100
Avg of 20 category scores
Critical defects
39
Likely production crashes
High-severity defects
80
Crash-prone or deprecated
Total findings
626
Each with file:line + fix
Modernization debt
68%
9,039 Java vs 4,347 Kotlin
Accessibility score
35/100
Compliance & legal risk
Build modernity
80/100
AGP 8.13 · Kotlin 2.2
Test files
~280
Unit + UI/instrumentation

At a glance

Severity distribution

Across 626 machine-curated findings

Health by area · sorted

12 areas · color = status

Industry-parity gap

Where we are vs where top retail apps are

Status by area

Twelve health areas grouped by domain. Each card describes what the area means, where the codebase stands today, why it matters to the business, and the recommended next step. Color stripe at the top of each card encodes status — green / amber / red.

Green — healthy (≥75) Amber — needs attention (60–74) Red — material risk (<60)
App Stability
Amber 60/100
What this means

How likely the app is to crash or freeze on real devices in production.

Current state

39 critical-severity defects across the codebase — Kotlin !! force-unwraps, unsafe as casts, unguarded getActivity() calls, list-index access without bounds checks. 96 memory-leak risk patterns additionally — Handler.postDelayed without cleanup, WebViews not destroyed, untracked coroutine Jobs. Concentration in MainWebViewFragment, FindAStoreFragment, MainActivity, WarehouseOffersFragment.

Why it matters

Each unhandled crash is a transaction lost during peak shopping hours. Sustained Crash-Free-Users decline cuts Play Store ranking, drives 1-star reviews, and erodes member trust. Memory leaks compound during long sessions and during the holiday shopping push.

Recommended next step

Stability strike-team — 2 senior engineers × 4 weeks fixing the top-20 by realized Crashlytics impact. Target: +2 percentage points crash-free-users within 1–2 release cycles.

Security Posture
Amber 70/100
What this means

Resistance to data theft, fraud, abuse, and tampering.

Current state

Strong baseline: HTTPS-only enforced, AES-256-GCM AndroidKeystore for tokens, biometric auth, R8 obfuscation, backup disabled, NowSecure scans in CI. Gaps: WebView lockdown incomplete (setAllowFileAccess(false) not set; addJavascriptInterface + dynamic loadUrl("javascript:…") in offers screen), no Play Integrity API, no FLAG_SECURE on payment / DMC screens, no data extraction rules file, certificate pinning import found but use needs verification.

Why it matters

WebView and dynamic JS-injection patterns are the typical entry points pen-testers find first. A successful exploit could exfiltrate session data or hijack payment flows. Lack of Play Integrity removes a key signal against fraud rings.

Recommended next step

Two-week WebView lockdown sweep + Play Integrity adoption + FLAG_SECURE on payment screens. Verify cert-pin activation. Address ahead of the next NowSecure scan.

Privacy & Compliance
Amber 68/100
What this means

Adherence to privacy law (GDPR / CCPA / PIPEDA) and Play Store policies.

Current state

~38 third-party SDKs shipping data off-device — Adobe Marketing Cloud (11 modules), Firebase, NokNok FIDO2, ThreatMetrix fingerprinting, Mastercard ClickToPay, Lucidworks, Contentstack. OneTrust integrated for consent. Email persisted unencrypted in DataStore; lat/lng cached on device. ACCESS_BACKGROUND_LOCATION used for warehouse geofencing — Play Store-sensitive permission. No SDK manifest or data-flow document.

Why it matters

Background-location reviews block releases when policy refreshes. CCPA / PIPEDA exposure if consent flow does not gate analytics. Data Subject Access Requests (DSARs) become engineering emergencies without a documented PII map.

Recommended next step

Verify Firebase Consent Mode v2 and Adobe consent flags gate analytics correctly. Encrypt cached email via the existing KeyStoreManager. Publish an SDK manifest + privacy disclosure update.

Performance
Amber 60/100
What this means

How fast the app feels — startup, scrolling, memory.

Current state

20+ dependencies eagerly initialized in CostcoApplication. Dual image libraries (Coil + Glide) and dual networking stacks (Volley + Retrofit/OkHttp) ship together. No baseline profile, no Macrobenchmark in CI. 8 runBlocking calls in production code (NewOnboardingViewModel alone has 8). 96 memory leak risk patterns trend memory upward in long sessions.

Why it matters

Slow cold start translates directly to lower engagement and retention. Play Vitals "slow start" + "slow rendering" flags reduce store visibility. OOM crashes on memory-constrained Android devices (still ~30% of the market) are unaddressed.

Recommended next step

Defer non-critical Application init paths via androidx.startup.Initializer. Generate a baseline profile for Home → PDP → Cart and ship it. Remove duplicate stacks (Glide and Volley).

Accessibility
Red 35/100
What this means

Ability for users with disabilities — vision, motor, cognitive — to use the app.

Current state

Near-zero contentDescription / Compose semantics adoption. WCAG 2.2 conformance: 3 FAILs (contrast 1.4.3, text resize 1.4.4, target size 2.5.5), 4 PARTIALs. No values-night across most modules. No font-scale 200% snapshot tests. No 48dp minimum target enforcement. RTL-locale resources absent.

Why it matters

AODA (Canada) / ADA (US) / Section 508 lawsuit exposure. Members with vision, motor, or cognitive impairments cannot reliably complete shopping flows. Brand reputation hit if reported by accessibility advocacy organizations. Failed audits block partnership with public-sector buyers.

Recommended next step

6-week accessibility sprint: 1 design-system + 2 feature engineers. Codemod for contentDescription across all Image/Icon; contrast validation in design-token build; Modifier.minimumInteractiveComponentSize() applied via a shared rule.

Localization Reach
Amber 62/100
What this means

How well the app serves users in different languages and regions.

Current state

Currently English + French (incl. Canadian variants en-rCA, fr-rCA). 693 locale resource directories total, 439 strings in main module. No RTL-locale resources. No LocaleManager.setApplicationLocales (Android 13 per-app language). No pseudo-locales in debug. Currency / date / plural formatters not consistently used (NumberFormat, DateTimeFormatter, getQuantityString).

Why it matters

Future Costco market expansion (Mexico, UK, Australia, Iceland, Sweden, Spain, Korea, Japan, Taiwan) means locale-specific bugs surface in production at scale. RTL-blind layouts will fail Hebrew / Arabic markets if those become targets.

Recommended next step

Add pseudo-locales (en_XA, ar_XB) in debug builds. Audit string concatenation of currency / dates / counts. Plan a one-week RTL audit pass when expansion targets firm up.

Architecture
Green 78/100
What this means

Quality of the codebase's structure, modularity, and decoupling.

Current state

56 modules (1 app + 22 features + 30 shared + 3 core/lib). Hilt DI with 60+ modules, repository + UseCase + ViewModel layers consistent in feature modules, version catalog. Concerns: shared/sdui exposes 209 public declarations with <1% internal; three util modules (util, blankutil, common) with overlapping responsibilities; MainActivity.java is a 5,411-line god-object.

Why it matters

Strong foundation lets the team ship in parallel. The few hotspots (MainActivity, sdui leaky surface) concentrate change cost and review friction, but the structure overall is healthy.

Recommended next step

Convention plugins in build-logic/ for android-feature, android-library, compose-feature. Sweep internal modifier into shared modules. Begin a multi-quarter MainActivity refactor.

Test Coverage
Amber 73/100
What this means

How much of the code is verified by automated tests.

Current state

~170 unit tests + ~80 instrumentation tests; modern stack (MockK 1.14.9, Turbine 1.2.1, kotlinx-coroutines-test 1.10.2, Compose UI Test, Karumi Shot screenshots, Hilt-testing). JaCoCo threshold 40.81% (low for a retail-scale app). Hilt-testing pinned at 2.28-alpha while Hilt 2.56 in main — version drift. MainCoroutineRule duplicated in 7 modules. JUnit 4 + 5 both present. No Macrobenchmark, no Firebase Test Lab in CI.

Why it matters

40% coverage means ~60% of changes don't run through any test gate. Test/runtime version drift can produce subtle DI bugs that pass tests but break in production.

Recommended next step

Stair-step JaCoCo threshold to 60–70% over two quarters; consolidate MainCoroutineRule into a shared/testfixtures module; bump Hilt-testing to 2.56; pilot Macrobenchmark.

Build Modernity
Green 80/100
What this means

How current the toolchain is — Gradle, AGP, Kotlin, dependencies.

Current state

AGP 8.13.2, Kotlin 2.2.0, Gradle 8.14.4, version catalog with 126 entries, R8 enabled in release, Compose BOM 2026.02.01, Hilt 2.56. compileSdk 36, minSdk 31, targetSdk 36. App Bundle structure works. Some bleeding-edge versions (Compose BOM Feb 2026) — verify Compose Compiler matches K2.

Why it matters

Modern toolchain unlocks new Android features quickly, applies security patches automatically, and helps recruiting. Real strength to protect.

Recommended next step

Add build-logic conventions to centralize plugin + Kotlin compile options. Pin known-good combinations. Enable build cache + configuration cache.

Tech Debt
Red 58/100
What this means

Accumulated work owed to the codebase that slows future work.

Current state

9,039 Java files vs 4,347 Kotlin (68% Java by file count). 197 TODO/FIXME/HACK markers across 88 files. Vendored DSLV + Raizlabs UniversalAdapter (third-party libraries inline). MainActivity.java at 5,411 lines. Dual stacks (Coil+Glide, Volley+Retrofit, Room+DBFlow). 30 shared modules with overlap. Stale README references SourceTree workflow, no ADRs, no per-module READMEs.

Why it matters

Each new feature ships a little slower; refactors are riskier; engineer onboarding and hiring become harder. The drag is invisible quarter-to-quarter but compounds.

Recommended next step

Migrate MainActivity.java + CostcoApplication.java to Kotlin first (highest leverage). Retire Volley + DBFlow + Glide. Consolidate util modules. Set quarterly Java-LoC reduction targets.

Engineering Velocity
Amber 70/100
What this means

How fast the team can ship features safely.

Current state

56 modules buildable in parallel (good for incremental builds). No build-logic / convention plugins — each module's gradle file is independent and prone to drift. Azure Pipelines CI with NowSecure scans. No Detekt / Ktlint baseline at the repo root. No CODEOWNERS — reviews are unrouted. JaCoCo 40% threshold doesn't actively gate. Hardcoded Maps API keys in committed gradle.properties create onboarding friction.

Why it matters

Reviews take longer than necessary; regressions slip through; new engineers spend their first week chasing setup issues instead of shipping.

Recommended next step

Add convention plugins; CODEOWNERS at the repo root mapping modules to teams; Detekt + Ktlint with baselines; Codecov / SonarCloud per-PR coverage diffs.

Operational Telemetry
Amber 70/100
What this means

Visibility into production behavior — logs, metrics, alerts, dashboards.

Current state

Firebase Crashlytics + Firebase Performance + Firebase Analytics integrated. Adobe Analytics + Adobe Target + Adobe Campaign (full marketing cloud). Timber + custom FirebaseRemoteLogger + ConsoleLoggerImpl. No clear PII scrubbing in release Timber tree. 8+ runBlocking sites are potential ANR sources without instrumentation. No defined error budget or rollback triggers.

Why it matters

Without consent-aware analytics, GDPR / CCPA risk. Without PII scrubbing, leaked logs become compliance issues. Without an error budget, the team can't make data-driven release decisions.

Recommended next step

Add ReleaseLoggerTree with PII scrubbing patterns; verify Firebase Consent Mode v2; instrument repository latency to feed Performance dashboards; define a quarterly error budget.

Top risks (business framing)

Each risk is framed by likely business impact, suggested owner, and rough effort. Severity reflects probability × impact.

1

Crash exposure on critical shopping flows

39 critical-severity defects in checkout, search, warehouse-finder, and product detail flows
Likely to translate into higher Play Store crash-free-users decline, lost transactions during peak shopping windows, and 1★ review spikes. Most concentrated in MainWebViewFragment, FindAStoreFragment, WarehouseOffersFragment, and MainActivity — all on critical retail user journeys.
StabilityRevenueReputationOwner: Mobile platform teamEffort: M
Severity
CRITICAL
2

Accessibility non-compliance

Effectively zero TalkBack support across Compose UI; legal & inclusivity risk
ADA / AODA / Section 508 exposure, particularly for a Canada-targeted retail app. Members with vision impairments cannot complete shopping flows reliably. Without intervention, Costco is an attractive target for accessibility lawsuits and regulator inquiries.
ComplianceBrandLegalOwner: Design system + feature teamsEffort: L
Severity
CRITICAL
3

Tech debt drag on velocity

9k Java files vs 4.3k Kotlin; 197 TODO/FIXME markers; dual image libraries
Engineering throughput is being slowly throttled by the Java/Kotlin split, the 30 overlapping shared modules, and an absence of build-logic conventions. This compounds: each new feature ships a little slower, each refactor is a little riskier, and onboarding new engineers takes longer.
VelocityCostHiringOwner: Platform / DX teamEffort: L
Severity
HIGH
4

WebView attack surface

JavaScript injection via dynamic loadUrl; addJavascriptInterface in offers WebView
WebView-based offers and pharmacy flows pass dynamic JavaScript via loadUrl("javascript:…") and bridge into native via addJavascriptInterface. If any HTML source is compromised or proxied, attackers could exfiltrate session data, call into the JS bridge, or redirect users. Pen-test priority.
SecurityPrivacyPCI-adjacentOwner: Security + WebView feature teamEffort: M
Severity
HIGH
5

Heavy app startup

20+ dependencies eagerly initialized in CostcoApplication
First-frame and time-to-interactive on cold start is paying for synchronous initialization of analytics, biometrics, geofencing, locale, fonts, and warehouse manager. This costs both user perception (slower-feeling app) and Google Play store-listing visibility (Vitals / Excessive Wakeups).
PerformanceVitalsUXOwner: Mobile platform teamEffort: S
Severity
HIGH
6

Background-location permission scrutiny

ACCESS_BACKGROUND_LOCATION used for geofencing warehouses
Google Play reviews background-location usage strictly. Any policy refresh or human review failure could block a release. Documented user-visible justification + foreground-only fallback reduces this risk meaningfully.
PrivacyPlay StoreReleasesOwner: Mobile + LegalEffort: S
Severity
MEDIUM
7

Stale documentation & onboarding

README references SourceTree workflow; KDoc coverage is sparse; no ADRs
New engineers take 2–3× longer to become productive. Architectural decisions are tribal knowledge — when the team rotates, expensive rediscovery is required.
HiringVelocityResilienceOwner: Tech leads + Eng ManagerEffort: M
Severity
MEDIUM

Recommended investment

Stability strike-team (now)

2 senior engineers x 4 weeks. Crash-free-users target +2.0 percentage points. ROI: directly visible in Play Store metrics within 1–2 release cycles.

Accessibility sprint (next)

1 design-system + 2 feature engineers x 6 weeks. Contains compliance risk; unlocks Costco-brand consistency. Concretely measurable via TalkBack acceptance tests.

DX investment (later)

1 platform engineer continuously. Convention plugins, build-logic, lint baselines. Pays back in faster CI builds + fewer flakes within 1 quarter.

Hold the line on basics

Maintain current strengths: Hilt DI, modularity, version catalog, build modernity, Coroutine discipline. These are real assets — protect them with conventions and PR gates.

Suggested roadmap

Now (next 30 days)

Stop the bleeding
  • Fix top-20 crash sites by Crashlytics impact (force-unwraps, getActivity guards).
  • Lock down WebView surface: addJavascriptInterface audit + content allowlist.
  • Enable Detekt with twitter/compose-rules + Ktlint baseline gate in CI.
  • Inventory background-location justifications & consent flow.

Later (3–6 months)

Compound the gains
  • Convention plugins (build-logic/) for android-feature / android-library / compose-feature.
  • Retire Volley; consolidate on Retrofit + Coil.
  • ADRs for BFF, Compose adoption, Hilt scoping. Refreshed README.
  • Per-feature Java→Kotlin burndown with quarterly LoC target.

Beyond (6+ months)

Become best-in-class
  • Dark mode + dynamic color (Material 3 You).
  • RTL-locale readiness; pseudo-locales in debug builds.
  • Macrobenchmark + Firebase Performance dashboards in product reviews.
  • Snapshot testing (Paparazzi) for design system regressions.

Where we stand vs. industry expectations

Solid bar shows current state; white tick shows industry expectation for a top-tier retail Android app. Gap analysis informs the roadmap above.

Crash-free users (target)
78/99
Cold start (P50, target)
55/80
Accessibility coverage
35/80
Test coverage (proxy)
73/70
Modernization (Kotlin %)
32/70
Build modernity
80/75
Security baseline
70/75
Documentation
50/70

Quick reference

If you have 2 minutes

Look at the headline indicators above. The two reds (39 critical defects, 35/100 accessibility) are where leadership attention is most useful.

If you have 10 minutes

Skim the Top Risks. Each maps to a recommended owner and effort estimate. Use this to set quarterly priorities.

If you want to dig in

The technical Overview dashboard has 6 charts and Excel export of every finding. Class-by-class gives engineers their working list.

For the board / partners

This page is print-friendly — use your browser's Cmd/Ctrl-P to produce a clean PDF. Sidebar and toolbars are hidden in print mode.

This view summarizes findings from a static-analysis review of the Costco Android codebase. Industry-comparison numbers are directional based on publicly observable benchmarks for top-tier retail Android apps; treat them as a frame of reference, not a contract.
Costco Android · Code Review Report · Generated 2026-05-07 · 142 machine-curated findings