Articles
Building AgroConnect
Over five days in October 2026, four of us built and shipped AgroConnect Ghana: an offline-first web app that lets agricultural extension agents register farmers in remote areas with zero cell reception, syncing everything to the cloud as soon as a connection is restored.
It is running live at app.agroconnect.space, with its API hosted in AWS Cape Town. The code is open source on GitHub, and our 2.5-minute walkthrough video shows how the app works for farmers, field agents, admins, and coordinators. This post explains what we were challenged to build, our architecture decisions, the parts I personally led, and where the project can go from here.
The live app as a farmer, a field agent, an admin and a coordinator.
The brief
Our Cloud Computing class (ICS 534) at Ashesi University gave us Prosit 1, "The AgroConnect Ghana Challenge". The goal was to build the foundational MVP of a farmer profiling platform tailored for rural Ghana, and justify every major architecture decision.
The operating environment is tough. Smallholder farms across the Northern, Upper East, Upper West, and Savannah regions frequently have zero 2G, 3G, or 4G connectivity. Field agents rely on budget, entry-level Android devices. Server traffic surges dramatically during brief subsidy windows, jumping from roughly 50 to 500 requests per second. On top of that, tight operational budgets mean you cannot afford to leave idle servers running between farming seasons.
The Week 1 requirements called for:
- A Progressive Web App that works completely offline and automatically syncs local data when connectivity returns
- Multilingual support for English, Twi, and Ewe, plus audio read-aloud features for low-literacy farmers
- SMS and USSD interfaces for farmers using basic feature phones
- Photo and GPS capture as verification for every registration
- A complete farmer profile: personal details, farm acreage, crop types, seasonal calendars, soil conditions, phone access, household income, mobile money details, and extension visit history
- Rigorously justified choices for the cloud region, database engine, authentication method, offline sync protocol, and data protection strategy
We worked as Group 3 (the Highlanders): I served as project manager (@josetseph), working alongside Eugene Sewor on cloud and DevOps, Elise Kennedy-Angbo on backend and data engineering, and Perfect Avugla on frontend engineering.
What we built
AgroConnect is a mobile-first web app backed by a secure, locked-down AWS setup. Four distinct user roles interact with the platform: farmers, field agents, administrators, and regional coordinators.
An agent can onboard a farmer in a few guided steps, capturing digital consent, a profile photo, and GPS coordinates entirely offline. Farmers can sign in to view their profile, check current market prices, read farming advice, look up weather forecasts, and manage their mobile money wallet. Administrators approve agent accounts, publish crop prices and advisories, and export registration data to CSV.
Left: with no signal, agents keep registering; everything waits on the phone. Right: back online, the queue sends and "Waiting to send" drops to 0.

How we first explained the design, mapped to the six AWS Well-Architected pillars.
The full picture: both AWS regions, CI/CD, observability and external services. Click to enlarge.
Every registration is saved to the phone's local IndexedDB first. Once an internet connection is detected, queued records flow through an AWS Application Load Balancer to private API containers. The API writes farmer profiles to PostgreSQL and uploads photos directly to Amazon S3. Only the load balancer is public-facing; the backend servers remain on private subnets.
The entire infrastructure is defined in Terraform and continuously deployed via GitHub Actions, monitored by CloudWatch alarms and a strict $100 monthly budget alert.
The decisions that shaped it
We documented our reasoning in 16 architecture decision records (ADRs). Here are the most significant choices we made, supported by our own empirical latency benchmarks from Ghana:
| Question | What we chose | Why |
|---|---|---|
| Which cloud region? | AWS af-south-1 (Cape Town) |
Rather than assuming, we measured network round-trip times from Ghana. Cape Town responded in 74 ms, beating London (117 ms), Azure South Africa (129 ms), and us-east-1 (175 ms). |
| How does offline work? | Save every change to the device first with a client-generated UUID | The app never blocks user input on network calls. If a sync request retries after a network drop, the server recognizes the client UUID and prevents duplicate farmer records. |
| SQL or NoSQL? | PostgreSQL 16 on Amazon RDS | Farmers, plots, extension visits, and payments have clear relational structures. A unique constraint on client-generated IDs enforces idempotency directly in the database engine, avoiding messy application-level deduplication. |
| How do farmers sign in? | Phone number, SMS OTP, then a 4-digit PIN | Almost all farmers have access to a mobile number, while fewer possess physical Ghana Cards. The PIN provides convenient offline session unlocking. |
| Which languages ship? | English, Twi, and Ewe | We did not have a native Dagbani speaker on the team and refused to ship unvetted machine translation. The app still allows recording Dagbani as the farmer's preferred spoken language. |
| How do we keep cloud costs low? | A t4g.nano NAT instance instead of a NAT Gateway; scale from 1 to 3 servers |
A custom NAT instance runs for about $3 a month, compared to roughly $32 for a managed AWS NAT Gateway. Under normal workloads, running a single server costs only about $10 a month. |
| How do deployments access AWS? | GitHub Actions with short-lived OIDC tokens | No persistent AWS credentials are stored in GitHub repository secrets. The production servers have no public IP addresses and no open SSH access. |
Median request round trip from Ghana in milliseconds, lower is better.
The cloud region decision was especially eye-opening. Most student projects default to us-east-1, but for users in Ghana, that adds about 100 ms of latency to every network trip. You really feel that extra delay when an agent reconnects and syncs dozens of registrations all at once.
What I did
As project manager, I oversaw the repository and reviewed every pull request touching shared architecture. During the final sprint, I also wrote a significant share of the code to close feature gaps:
Backend and infrastructure
- Built the production PostgreSQL API covering all frontend data contracts. I ported our team's mock server along with its 89 contract tests to ensure the real backend satisfied every specification. I also integrated Elise's foundational backend work, including security headers, unique request IDs, structured JSON logging, and graceful shutdown handling (ADR-013).
- Configured container runtime secrets and environment variables in Terraform, resolving an issue where the container could not retrieve AWS credentials due to the IMDSv2 metadata hop limit.
- Implemented zero-downtime rolling deployments by provisioning new container instances before terminating old ones (#33), and resolved CI pipeline failures triggered by concurrent instance refreshes.
- Integrated Nalo Solutions for sending SMS authentication codes, keeping Arkesel configured as an automatic fallback provider (#80).
Features for farmers and agents
- Authored the Twi and Ewe localization strings and proposed omitting Dagbani from UI text rather than relying on flawed machine translation (ADR-010).
- Built Service Worker Background Sync to ensure offline submissions upload even if the agent closes the browser, using Web Locks to prevent overlapping sync jobs (ADR-012).
- Built the interactive USSD interface for feature phones, enabling farmers to check commodity prices, read farming tips, register, request extension visits, and view weather reports (#50). It runs live on the short code
*920*260#: during our demo, classmates dialled it on their own phones, checked a crop price and requested an agent visit, and the request appeared for the coordinator in the app. - Implemented text-to-speech audio playback for low-literacy users (#55), the extension officer visit logger (#53), and Web Push notifications for farmer inquiries, payments, advice, and agent approvals (#58).
- Expanded the registration workflow to capture the entire farmer profiling schema required by the challenge (#46), built admin management tools for market pricing and advice cards (#30), added a PWA install prompt, and implemented per-role code splitting (#57).
Documentation and delivery
- Established the documentation hub and authored remaining ADRs covering databases, authentication, and data protection (#59).
- Created the deliverables trace matrix, linking every assignment requirement directly to the supporting source code.
- Published an AI tools disclosure detailing where and how Claude Code assisted across commits.
- Re-recorded and captioned the product walkthrough video against our live production deployment (#78).
What I learned
Measure before making assumptions: It is tempting to guess that European cloud regions offer faster connectivity to West Africa than South Africa does. Empirical latency testing proved otherwise, and that simple benchmark settled our most consequential infrastructure decision.
Infrastructure as Code has real-world edges: AWS Amplify Hosting is not available in the Cape Town (af-south-1) region. Furthermore, Terraform cannot provision an Amplify app connected through the GitHub App because AWS only exposes that integration via the web console. We provisioned the Amplify app manually once, imported it into Terraform state, and documented the manual prerequisite in our repository. Transparently documenting a single manual step was far better than abandoning IaC altogether. You can read the full journey in our engineering learnings.
Contract-first development keeps parallel teams moving: Writing API contracts and setting up a mock server first let the frontend team build against mock endpoints while the backend was still under construction. When the live PostgreSQL API was finished, our 89 contract tests verified that both implementations matched.
Rely on the database for hard guarantees: Offline-first clients inevitably retry network requests. Enforcing uniqueness on client-generated UUIDs at the PostgreSQL level ensured that no timeout, network flicker, or client retry could ever insert duplicate records.
AI assistance accelerates delivery only when paired with rigorous review: Claude Code was a huge productivity booster during development. However, every AI-assisted code change still went through pull requests, strict code owner reviews, and automated CI test suites before landing on the main branch.
Where it goes next
Our Week 1 deliverable is complete, though certain integrations wait on external activation. Looking ahead, here is the roadmap:
Activating pending integrations
- Configure production VAPID credentials to begin dispatching push notifications
- Record native Twi and Ewe audio files for audio read-aloud buttons
- Partner with a native Dagbani speaker to translate the UI strings
Field validation with farmers
- Conduct usability testing with the Ashaiman Urban Farmers Association (whose profiles are pre-seeded in the app)
- Run a live pilot registration drive with rural agricultural extension agents
- Establish respectful community engagement protocols with local chiefs and elders
Platform hardening
- Migrate the database to an Amazon RDS Multi-AZ configuration to guard against single-zone outages
- Perform stress tests simulating the 50 to 500 requests per second subsidy registration spikes against our autoscaling configuration
- Implement the remaining data protection safeguards detailed in ADR-016
Future scope from the course brief
- Multi-country data sovereignty and regional database sharding across Africa
- Support for Yoruba and Swahili
- Algorithmic credit scoring and micro-insurance risk assessments derived from farmer profiles
- Computer-vision crop disease detection using uploaded farm photos
- Real-time commodity exchange integrations to replace manual admin pricing
Links
- Code: ASU-MICS-2028/cc-group-3-prosit-1
- Live app: app.agroconnect.space
- API health check: api.agroconnect.space/health
- Walkthrough video: in the README
- Architecture: system overview and decision records
- Region benchmarks: empirical research
- Requirement-by-requirement trace: Prosit 1 deliverables
- AI use: AI-tools disclosure
