Mobile Apps
Retail Loyalty App Rewrite
Built by Joshua Enriquez
Native Android rewrite of a retail chain's loyalty app after the previous hybrid version stalled on performance.
Builder email verified
Verification
- Type
- Professional
- Category
- Mobile Apps
- Published
- Jul 25, 2026
- Updated
- Jul 25, 2026
About this project
- The problem
The chain's existing loyalty app had poor ratings, and the reviews were consistent: slow to open, slow to show the barcode people needed at the till, and it logged you out. That last one was fatal — a customer standing at a checkout with a queue behind them will not sign in again, they'll just stop using the app. Store staff had started keeping a manual workaround for customers whose app failed. The brief was a rewrite focused on the checkout moment rather than on new features, which took some arguing to protect.
- My role
I was the Android developer on a team of three — me, an iOS developer and a backend developer — with a product manager on the client side. I owned the whole Android application. It was my first project as the only person on a platform, and the parts I found hardest were the ones nobody could review for me.
- What I owned
I built the Android app from scratch: authentication and session handling, the points and rewards screens, the barcode display, offer redemption, and the store locator. I owned the caching strategy that makes the barcode available instantly and offline, which was the actual point of the project. I did the Play Store release process, the staged rollout configuration, and the crash triage after launch. I did not own the backend or the iOS app, though the iOS developer and I agreed the shared behaviour together.
- Technical & product decisions
The decision that mattered most was caching the loyalty barcode locally and rendering it without a network call or a session check. The previous app validated the session before showing it, which is defensible and is exactly why it failed at the till. I made the barcode a locally stored artifact that refreshes in the background, and moved session validation to everything else. I also chose long-lived refresh tokens with silent renewal against some resistance, because the security posture of a loyalty points balance does not justify logging people out weekly. I used Jetpack Compose for the whole app, which was the riskier choice for me personally since I'd only used it in small pieces, and I spent the first three weeks slower than I would have been otherwise.
- Constraints
The backend was shared with the old app and couldn't change much, so the offline barcode had to be built from what existing endpoints returned. The chain's customers skew toward older devices — a meaningful share on Android versions several years old — which ruled out some APIs and made me test on a genuinely slow device rather than an emulator. We also inherited the existing user base and their sessions, so migration had to happen without a forced re-login, which was the opposite of what the old app did to people.
- Result & impact
Cold start to a scannable barcode went from around six seconds, when it worked, to under a second from cache. The store rating moved from 2.4 to 4.1 over about four months, and the review themes changed from logging out and slow to feature requests, which I'll take. Scans per active user rose noticeably in the first quarter — the client's figure was around forty percent, though a promotion overlapped so I'd hold that loosely. Store staff stopped using their manual workaround, which the product manager mentioned in passing and which told me more than the numbers.
- Who else worked on it
The iOS developer and I worked out the shared session and caching behaviour together, and his session handling design was better than my first attempt so I took it. The backend developer added two endpoints to make offline redemption possible and was patient about my third revision of the request. The client's product manager defended the narrow scope against feature requests from the marketing team for four months, which is why the project worked.