Building for Low-Bandwidth: The Technical Decisions Behind Curriva's Performance
45% of Nigerian internet users are on 3G. Our application had to work for them. Here are the specific technical decisions we made and the performance numbers that resulted.
Written by Curriva Team
Nigeria's internet infrastructure is improving, but it is not uniform. In urban areas like Lagos and Abuja, 4G coverage is extensive. In rural areas and smaller cities, 3G is still the primary connection. According to GSMA data (2024), approximately 45% of Nigerian mobile internet users are on 3G connections.
For an education tool that needs to work for teachers across the country, this is not an edge case. It is the default. Here are the technical decisions we made to handle it.
Decision 1: Static Generation for Content Pages
Next.js supports static generation (SSG), server-side rendering (SSR), and client-side rendering. For content-heavy pages, curriculum browsing, blog posts, about pages, we use static generation.
The result: these pages load in under 2 seconds on 3G connections. The HTML is served from Vercel's edge network, which has PoPs (Points of Presence) in Lagos. The browser does not need to make additional requests for the core content.
We tested with Lighthouse on a simulated 3G connection (1.5 Mbps download, 750ms latency). Static pages scored 95+ on performance. SSR pages scored 70-80. Client-side rendered pages scored 40-55.
Decision 2: Image Optimization
Images are the largest bandwidth consumers on education platforms. A teacher uploading a diagram of the circulatory system might submit a 5 MB PNG. Serving that to a student on 3G would take 27 seconds.
We use Next.js Image component with automatic format conversion and responsive sizing:
- Format conversion: PNGs are converted to WebP, reducing file size by 60-80% with no visible quality loss.
- Responsive sizing: Images are served at the size needed for the display, not the original upload size. A thumbnail is 200px wide. A card preview is 400px. A full view is 1200px.
- Lazy loading: Images below the fold are loaded only when the user scrolls to them. This reduces initial page load time.
- Blur placeholder: While an image loads, a blurred placeholder is shown. The user sees content immediately, not a blank space.
For example, a circulatory system diagram (5 MB original) is served as WebP at 180 KB for mobile view, 420 KB for tablet, and 680 KB for desktop. On 3G, the mobile version loads in 1 second.
Decision 3: Data Transfer Budgets
We set explicit data transfer budgets for each page type:
- Curriculum browsing page: 50 KB total transfer (HTML, CSS, JS, and data). On 3G, this loads in 1.5 seconds.
- Resource editor: 120 KB for the initial load. Additional widgets load on demand as the educator adds them.
- Blog post: 30 KB for the content. Images load lazily.
- Survey page: 25 KB. The survey is intentionally lightweight.
These budgets are enforced through build-time analysis. If a page exceeds its budget, the build warns and we investigate.
Decision 4: Local-First Data Sync
For the resource editor, we use a local-first approach:
- Drafts saved locally: When an educator is creating a resource, changes are saved to the browser's IndexedDB immediately. No network request needed.
- Background sync: Changes are synced to Supabase in the background when the connection is available. The user sees a "synced" indicator when the sync completes.
- Conflict resolution: If two users edit the same resource (in the institutional layer), conflicts are detected and resolved using last-write-wins with manual merge options.
- Offline editing: The educator can close the browser, lose internet connection, and reopen the editor. Their draft is still there, locally stored. When the connection returns, it syncs.
Editor responsiveness (time from keystroke to display) is 16ms locally versus 200-400ms with server-side sync. On 3G, the difference is even more pronounced: 16ms versus 800-1200ms.
Decision 5: API Response Optimization
Server-side API routes use several optimization techniques:
- Field selection: API responses include only the fields the client needs. No SELECT * queries. A curriculum browsing request returns topic titles, IDs, and metadata, not the full content of every topic.
- Pagination: Large result sets are paginated. A search for "Mathematics" topics returns 20 at a time, not 200.
- Compression: All API responses use gzip compression. A 50 KB JSON response compresses to approximately 12 KB.
- Caching headers: Static data (curriculum structure, widget types) uses Cache-Control: max-age=86400 (24 hours). Dynamic data (user resources, analytics) uses Cache-Control: no-cache with ETags.
API response times for typical requests (curriculum browsing, resource listing) are 50-150ms on 4G, 150-400ms on 3G. The compressed response sizes are typically under 20 KB.
Decision 6: Progressive Enhancement
The application works without JavaScript enabled. Core functionality, curriculum browsing, resource viewing, survey completion, is available as server-rendered HTML. JavaScript enhances the experience (animations, real-time updates, offline support) but is not required for basic use.
This matters for educators using older devices where JavaScript execution is slow, or browsers where JavaScript is disabled for performance reasons.
The Results
We tested Curriva on five device and connection combinations:
- iPhone 14, 4G: All pages load under 2 seconds. Editor responsive at 16ms.
- Samsung Galaxy A12, 4G: All pages load under 3 seconds. Editor responsive at 20ms.
- Samsung Galaxy A12, 3G: All pages load under 5 seconds. Editor responsive at 25ms locally, 900ms with server sync.
- Tecno Spark, 3G: All pages load under 7 seconds. Editor responsive at 30ms locally, 1200ms with server sync.
- Tecno Spark, 2G: Static pages load under 10 seconds. Editor functional but slow for server sync (2+ seconds). Local-first approach keeps the editor usable.
The Tecno Spark on 3G is the baseline we design for. If it works there, it works everywhere.
What We Still Need to Improve
- First-load experience: The initial JavaScript bundle is 180 KB (gzipped). On 2G, this takes 8+ seconds to download. We are working on code splitting to reduce this.
- Search performance: Full-text search currently requires a server round-trip. On 3G, this adds 400-800ms. We are exploring client-side search with a pre-loaded index.
- Image upload: Uploading large images on 3G is slow. We are implementing client-side compression before upload.
Performance is not a feature. It is a prerequisite. If the tool is slow, it will not be used. Every technical decision we make is evaluated against the question: "Does this work on a Tecno Spark on 3G?"
Related Reading
For how the widget system loads on demand, for how the three resource layers handle offline sync, and for how the institutional workspace manages shared resources.
Experience Curriva's performance on your device
Experience Curriva's performance on your deviceFrequently Asked Questions
What percentage of Nigerian internet users are on 3G?
How fast do Curriva pages load on 3G?
Does Curriva work offline?
What devices did Curriva test on?
Related Reading
Institutional Workspace: How Schools Manage Resources at Scale
A school with 30 teachers generates hundreds of teaching materials per term. Without a system, those materials vanish when teachers leave. Here is how Curriva's institutional workspace solves this.
Widget Architecture: How Curriva's Editor Understands Educational Content
We built 70 widget types, not because we wanted to, but because educational content has structure that a blank document cannot represent. Here is how the system works and why each widget exists.
Three Resource Layers: Personal, Institutional, and Public
Teaching materials do not exist in a vacuum. They belong to an individual, an institution, and a community. Curriva's architecture reflects this reality. Here is how the three layers work.