All Articles
World BankGeospatialPostgreSQLPWAKenya

Building a Geospatial Platform for the World Bank: Lessons from KISIP II

How I architected an enterprise PWA processing 50,000+ daily API requests for the World Bank's Kenya Informal Settlement Improvement Project, coordinating 282 youth workers across 7 settlements.

November 15, 20254 min read

The Challenge No One Warns You About

When you hear "World Bank project," you imagine well-funded teams with clear specifications. The reality of KISIP II was different. We needed to deploy a field data platform across seven of Nairobi's most densely populated informal settlements — Kibera, Mathare, Mukuru, Kayole, Dandora, Korogocho, and Kariobangi — with workers who had never used enterprise software.

The existing process was entirely paper-based. Field supervisors carried clipboards. Payment reconciliation took weeks. Nobody could answer the question: "How many tasks were completed today?"

Architecture Decisions That Mattered

Why a PWA, Not a Native App

The workers carried budget Android devices with intermittent connectivity. A native app would have meant Play Store deployment cycles, device fragmentation testing, and 50MB+ downloads over expensive mobile data. A Progressive Web App gave us:

  • Offline-first architecture with service workers caching task queues
  • Instant deployment — push updates hit all 282 workers simultaneously
  • 2MB initial payload vs. 50MB+ for a comparable native app
  • No app store gatekeeping — critical when you need to deploy on government timelines

The 76-Table PostgreSQL Schema

The schema wasn't complex because we wanted it to be. It was complex because the real world is complex. A single "task" — say, painting a road marking in Kibera — touches:

  • Worker assignment (who was assigned, when, by which supervisor)
  • Geospatial data (GPS coordinates, which settlement polygon, which ward)
  • Verification chain (field photo, supervisor approval, QA check)
  • Payment linkage (which payment cycle, M-Pesa disbursement status)
  • Audit trail (every state change timestamped for World Bank compliance)

We used PostGIS extensions for spatial queries — finding all tasks within a settlement boundary, calculating coverage percentages, identifying gaps in surveyed areas.

ODK Central Integration

Field data collection ran through ODK Central with custom XLSForms. The key insight was treating ODK as a data collection layer, not a database. Submissions flowed through a webhook pipeline:

  1. Worker submits form on ODK Collect (works offline)
  2. ODK Central receives and validates
  3. Our middleware transforms and enriches with geospatial context
  4. PostgreSQL stores the canonical record
  5. Real-time dashboard updates via WebSocket

Scaling to 50,000+ Daily API Requests

When 282 workers start their shift at 7 AM, the system sees a traffic spike that would embarrass most startups. Every worker's device syncs cached offline data, pulls updated task assignments, and begins streaming GPS pings.

We handled this with:

  • Connection pooling via PgBouncer — 20 persistent connections serving hundreds of concurrent users
  • Materialized views for dashboard aggregations — pre-computed daily/weekly/monthly rollups refreshed every 15 minutes
  • CDN-cached static assets — the PWA shell loads from cache while API calls fetch fresh data
  • Request batching — the client queues individual task updates and sends them as a single batch POST every 30 seconds

The Payment Problem

Paying 282 workers accurately and on time through M-Pesa was the feature that made or broke trust. In previous projects, workers waited 2-3 weeks for manual reconciliation. We built an automated stipend engine:

  1. Worker completes verified tasks throughout the payment period
  2. System calculates earnings based on task type and completion quality
  3. Supervisor reviews and approves batch payment
  4. M-Pesa Business-to-Customer (B2C) API disburses funds
  5. Worker receives SMS confirmation within minutes of approval

This reduced payment cycles from weeks to hours and eliminated the manual spreadsheet reconciliation that previously consumed 3 full-time staff.

What I'd Do Differently

More aggressive caching. We played it safe with 15-minute materialized view refreshes. In hindsight, 5-minute refreshes with targeted invalidation would have given supervisors near-real-time dashboards without significant database load.

Better onboarding flows. We underestimated how much hand-holding field workers would need. The first week saw support tickets about basic navigation. Building an interactive tutorial into the PWA would have saved dozens of in-person training hours.

API versioning from day one. We shipped v1 and assumed we'd iterate. We did iterate — and coordinating breaking changes across 282 devices taught us that API versioning isn't optional infrastructure, it's survival infrastructure.

The Numbers

After 18 months in production:

  • 1.7 million weekly tasks processed at peak
  • 50,000+ daily API requests sustained
  • 282 youth workers coordinated across 7 settlements
  • 3 payment cycles reduced from weeks to hours
  • Zero data breaches — Kenya Data Protection Act compliant throughout

The platform continues to operate today, managed by government staff trained during the handover phase. That's the real metric of success — building something that outlasts your involvement.

Related Case Study

Read the full case study