Kazimedia
← Back to blog

22 January 2025

6 min read

Building for Low Bandwidth: Performance Lessons from Uganda

When your users switch between 4G and EDGE several times a day, performance is not optional. These are the techniques we use to keep our applications fast on any connection.

Building for Low Bandwidth: Performance Lessons from Uganda

One of the most important things we learned early at Kazi Media is that the internet experience in East Africa is fundamentally different from that in Europe or North America. Users do not sit on fibre broadband. They use mobile data — often rationed data — and they expect your application to work regardless.

Here are the most impactful optimisations we apply to every project.

1. Aggressive Image Optimisation

Images are typically responsible for 60–80% of a page's total byte weight. We use WebP format for all images, which offers 25–35% smaller file sizes than JPEG at equivalent visual quality. On Next.js, the built-in <Image> component handles WebP conversion automatically and serves appropriately sized images via srcset.

For hero images, we target a maximum file size of 150 KB. For thumbnails, 20 KB. These numbers sound aggressive but are achievable with modern compression tools like Squoosh or Sharp.

2. Lazy Loading Everything Below the Fold

Only load what the user actually needs. Images, carousels, maps, and heavy UI components that appear below the visible viewport should be lazy-loaded using the loading="lazy" attribute or React's Suspense boundary. This reduces initial page weight dramatically.

3. Minimise Third-Party Scripts

Every third-party script — analytics, chat widgets, ad pixels — adds latency. We audit third-party scripts rigorously on every project. Where possible, we defer non-critical scripts using the strategy="lazyOnload" prop in Next.js. A page that triggers ten third-party requests will always load slower than one that triggers two.

4. Effective Caching Strategy

Static assets (JavaScript bundles, CSS, fonts, images) should be served with long cache headers so repeat visitors do not re-download them. Dynamic content (API responses) should use stale-while-revalidate to serve cached data immediately while fetching updates in the background.

5. Fonts: Subset and Self-Host

Google Fonts are convenient but add an extra DNS lookup and round-trip for the user. We use next/font to self-host web fonts, which eliminates the external request and applies font-display: swap by default so text remains readable while the custom font loads.

The Result

Applying these techniques consistently, we routinely achieve Google Lighthouse scores above 90 for performance — even for sites with rich imagery and complex interactions. On a mid-range Android device on a 3G connection, our pages typically become interactive in under three seconds.

Performance is not a luxury. It is a baseline requirement. Talk to us if you want to audit or improve the performance of your existing application.

All articles

Have a project in mind?

Get in touch →