Andres dos Santos

Solving an Invisible Performance Bottleneck: Reducing S3 Egress in a Mobile Banking App

Identified and solved an unnecessary S3 egress issue in a mobile banking app by redesigning image loading to prioritize local storage, reducing network requests, latency, and improving scalability.

While working on a mobile banking application, I noticed an architectural issue related to image loading.

A shared component was being used across multiple screens (Home and Settings), and every time the component mounted, a useEffect triggered a request to fetch the user's profile image from AWS S3.

At first, this didn’t make sense to me.

If AWS charges for data transfer and every request adds network overhead, why were we downloading the same image every single time the component rendered?

Instead of treating this as a minor inefficiency, I proposed an improvement and designed a new flow.

Previous flow

Component mounts: API request -> S3 image download -> render image.

This meant that every screen visit triggered:

  • Network latency
  • DNS lookup
  • TLS handshake
  • Image download
  • Additional S3 egress costs

It also introduced scalability concerns. For example, imagine a push notification being sent to thousands of users. If many users open the app simultaneously, every request would trigger:

App -> API -> S3 -> Image download

Creating an unnecessary bottleneck between the API and S3.

My solution

I redesigned the image loading strategy:

User updates profile image: Save image locally -> save image in AWS S3 -> Component loads local image.

User updates profile image: → Save image locally → Save image in AWS S3 → Component loads local image.

Instead of downloading the image every time, the app now prioritizes the locally stored version and only re-fetches when necessary.

Why this matters

Although the change seems simple, it improved several engineering concerns:

  • Reduced unnecessary S3 egress
  • Fewer network requests
  • Better perceived performance
  • Lower latency during screen rendering
  • Improved resilience during traffic spikes

This experience reinforced something important to me: many performance problems are not obvious. Sometimes, meaningful improvements come from questioning small implementation details that everyone else has normalized.