Skip to content

TrafficGrid System Design

Microservices Architecture

1. Project Overview


TrafficGrid consolidates vehicle records, traffic offences, parking fines, and payment processing for Harare into a single unified digital platform. Officers log offences via mobile. Citizens view their vehicle records and pay fines electronically. All actions are audited.

This document is version 2.0, superseding v1.0. The core microservices architecture is unchanged. This revision corrects the service inventory (notifications-service is now a dedicated service rather than co-located in payments-service), removes system-parameters from the shared-library category (it is a running process), and adds RabbitMQ for all asynchronous communication.

2. Service Inventory


The system is composed of 10 running processes. core-service is a shared Maven dependency (published to GitHub Packages) — it is not a running process.

Service Port Responsibility
discovery-service 8761 Eureka service registry - all services register here on startup
config-server 8888 Centralised configuration served to all services from Git or classpath
api-gateway 8080 Single entry point — auth validation, routing, rate limiting, SSL termination
auth-service 8081 User registration, login, JWT issuance, refresh token rotation, RBAC
audit-service 8082 Receives audit events and persists immutable audit_logs records
system-parameters-service 8083 settings in the system like currencies, notification channels, organizations, fine categories
vehicle-service 8084 vehicles, vehicle documents, citizen vehicle records
fines-service 8085 fines, parking tickets
payments-service 8086 handles payments, payment items
notifications-service 8088 notifications, notification preferences
#### core-service
core-service is a shared JAR dependency published to GitHub Packages. It is imported by all services as a Maven dependency. It is not deployed or registered with Eureka. It contains: response envelope shape, pagination wrappers, common exception types, and shared HTTP error handling. Domain-specific concerns (enums, entity classes, business logic) must never be placed in core-service — each service owns its own domain types unless it's explicitly needed to be a global dependency.

3. Architecture Style


Each domain service owns its own PostgreSQL schema (or separate database). No service queries another service's database directly. Cross-service data is accessed through HTTP API calls (via OpenFeign) or consumed via asynchronous events published to RabbitMQ exchanges.

All client traffic (mobile, web, officer app) enters exclusively through the API Gateway. The gateway validates JWT tokens and forwards decoded claims as request headers (X-User-Id, X-User-Role, X-Organisation-Id) so downstream services do not need to call auth-service on each request.

3.1 Communication Patterns

Pattern When Used Example
Synchronous Rest (OpenFeign) Query-response where the caller needs data immediately fines-service calls vehicle-service to verify a vehicle exists before issuing a fine
OpenFeign to system-parameters Runtime reference data lookup Any service calls system-parameters to resolve currencies or notification channel config
Async RabbitMQ events State changes that other services react to independently payments-service publishes to trafficgrid.payments exchange; notifications-service and fines-service both consume from it
Gateway header forwarding Propagating auth context to downstream services Gateway decodes JWT and sets X-User-Role: ZRP_OFFICER on every forwarded request

3.2 RabbitMQ — Message Architecture

TrafficGrid uses RabbitMQ with topic exchanges. A topic exchange routes messages based on a routing key pattern, allowing multiple consumers to bind to the same exchange with different routing key filters. This is the recommended pattern for event-driven microservices because it decouples producers from consumers: a producer publishes to an exchange and does not know which services consume the message.

Exchange and Routing Key Design

Exchange Type Routing Key Pattern Description
trafficgrid.vehicles topic vehicle.* Vehicle domain events
trafficgrid.fines topic fine.* Fine and parking ticket events
trafficgrid.payments topic payment.* Payment transaction events
trafficgrid.notifications topic notification.* Notification dispatch commands (internal)
Events By Exchange
Exchange Routing Key Publisher Consumers Trigger
trafficgrid.fines fine.created fines-service audit-service, notifications-service New fine issued against a vehicle
trafficgrid.fines fine.status.updated fines-service audit-service, notifications-service Fine cleared, cancelled, or disputed
trafficgrid.payments payment.success payments-service fines-service, audit-service, notifications-service Payment confirmed by provider
trafficgrid.payments payment.failed payments-service audit-service, notifications-service Payment declined or failed
trafficgrid.vehicles vehicle.document.expiry vehicle-service notifications-service Vehicle document within 30 days of expiry

Queue Binding Pattern Each consumer service declares its own durable queue and binds it to the relevant exchange with a routing key. For example, notifications-service declares a queue named notifications.fine.events and binds it to trafficgrid.fines with routing key fine.# to receive all fine events. This means adding a new consumer never requires changes to the publisher.

notifications-service Communication Model notifications-service is event-driven for sending notifications and exposes REST endpoints for notification history. It consumes events from RabbitMQ (fine.created, fine.status.updated, payment.success, payment.failed, vehicle.document.expiry) to trigger outbound messages. No other service calls it directly to send a notification. REST endpoints (GET /notifications, GET/PUT /notifications/preferences) are called directly by authenticated clients via the API Gateway.

4. Stakeholders & Integrations


4.1 Organizations in Scope

Organisation Role Integration Type Status
ZRP Issues traffic fines. Officers log via mobile app. Manual entry — officer mobile app Active
City Council (Harare) Issues council fines and violations. Manual entry — council officer portal Active
ZINARA Source of vehicle licence and registration data. REST API integration (mocking for the meantime) Planned
VTS (Vehicle Theft Squad) Verifies VIN numbers and vehicle ownership. REST API integration (mocking for the meantime) Planned
City Parking Issues parking tickets. REST API integration (mocking for the meantime) Planned
System Provider (ShiftFocus) Builds and administers the platform. Full super-admin access Active
### 4.2 Out of Scope — Phase 1
- ZIMRA — vehicle import duties and tax clearance
- Foreign vehicle registration
- Insurance provider API integration

5. User Roles


Role Internal Enum Description
General Public / Citizen CITIZEN Self-registered. Views own vehicles, fines, renewal reminders. Pays online.
ZRP Officer ZRP_OFFICER Logs traffic fines from mobile. Searches vehicle history. Cannot see unrelated records.
City Council Officer COUNCIL_OFFICER Logs council fines. Queries outstanding fines on a vehicle.
City Parking Officer PARKING_OFFICER Manages parking tickets. Scoped to parking data only.
Authority Admin AUTHORITY_ADMIN Supervisor within one organisation. Read-only reports scoped to their org.
Super Admin SUPER_ADMIN Full system access. User management, cross-authority reporting, audit log access.

6. Functional Requirements

6.1 Vehicle Management

  • Officers can create vehicle records when issuing fines against vehicles not yet in the system
  • Citizens link vehicles to their account by number plate
  • Each vehicle has a dashboard: registration details, active fines, linked documents, renewal dates
  • Vehicle data sourced from VTS and ZINARA via API (dummy data during develo pment)
  • Vehicle documents (licence, insurance, ZBC, fitness) tracked with expiry dates
  • Citizens can self-declare document expiry dates until ZINARA integration is live

6.2 Fines

  • ZRP and Council officers issue fines against a vehicle from their mobile device
  • Fine amount is copied from the category at issue time and frozen — never retroactively changed
  • Each fine has a status: PENDING, PAID, CLEARED, DISPUTED, CANCELLED
  • Default payment window: 30 days from issue date
  • Admins can manually clear or cancel fines with a mandatory reason for audit purposes
  • Officers can record cash payments on the spot, creating an audited paper trail

6.3 Parking Tickets

Status: Planned — pending City Parking API integration. parking_tickets owned by fines-service. - Parking tickets sync from City Parking's system or are entered manually by parking officers - Tickets appear on the relevant vehicle's record - Tickets are payable through the same payments infrastructure as fines

6.4 Payments

  • Supported methods: EcoCash , bank transfer (swipe) , cash recorded by officer
  • A single payment can settle multiple fines and/or parking tickets in one transaction
  • Payment is idempotent — duplicate attempts using the same idempotency key are safely rejected
  • payment.success RabbitMQ event automatically marks associated fines as PAID
  • Full payment receipts generated and accessible to the vehicle owner
  • Partial payments are out of scope for Phase 1

6.5 Notifications

  • Citizens receive notifications when a new fine is issued against their vehicle
  • Citizens receive reminders for upcoming vehicle document expiry (30 days before)
  • Citizens receive confirmation when a payment succeeds
  • Notification channels are configured in system-parameters; citizens choose their preferred channel per their notification_preferences record
  • Notification history is queryable via REST. Sending is triggered exclusively by RabbitMQ events.

6.6 Audit & Transparency

  • Every write action logged with: actor, role, organisation, timestamp, IP, before/after state
  • Audit logs are immutable — never updated or deleted
  • Super admins access full audit log; authority admins see logs scoped to their organisation
  • Includes: fine creation, payment recording, manual clearances, user account changes

7. Non-functional requirements

Concern Requirement
Security JWT-based auth. RBAC enforced at gateway and within each service. Officer mobile sessions protected.
Rate Limiting API gateway enforces per-user and per-role rate limits on all endpoints.
Idempotency Payment endpoints are idempotent. Duplicate requests for the same fine never result in double charges.
Race Conditions Concurrent payment attempts on the same fine handled via optimistic locking or distributed lock on the fine ID.
Scalability Services are independently deployable and horizontally scalable. Initial scope is Harare — national expansion must not require re-architecture.
Auditability Every state-changing action emits an audit event consumed by audit-service. Logs stored as JSONB snapshots.
Availability Fine lookup and payment processing target high availability. Degraded mode acceptable for notifications.
Offline Support Officer mobile app supports offline fine logging with queue-and-sync when connectivity is restored.

8. Client Interfaces

Interface Users Notes
Citizen Mobile App General Public Android and iOS. Vehicle dashboard, fines, payments, renewal reminders. Mobile-first
Officer Mobile App ZRP and Council officers Android. Offline-capable fine logging. Secure login. Syncs on connectivity restore.
Web Portal Authority admins Query vehicle records, view scoped reports, manage manual clearances.
Admin Portal SUPER_ADMIN Full system oversight, user management, audit log access, cross-authority reporting.
USSD and WhatsApp interfaces are planned for a future phase to increase accessibility for users without smartphones.

9. Infrastructure


All infrastructure (PostgreSQL, Redis, RabbitMQ) runs in Docker containers. Services themselves can run as plain Java processes connecting to containerised infrastructure, or all 10 services can be containerised and orchestrated via Docker Compose.

Component Docker Image
PostgreSQL postgres:16-alpine — one container, multiple databases or schemas per service
Redis redis:7-alpine
RabbitMQ rabbitmq:3-management — includes management UI at http://localhost:15672

A docker-compose.yml in the project root should define these three infrastructure services. Java services connect to them via config-server properties (spring.datasource.url, spring.rabbitmq.host, etc.).

9.2 Production (Future)

  • Containerisation: Docker — each service packaged as an image
  • Orchestration: Kubernetes — manages deployment, scaling, and self-healing
  • CI/CD: GitHub Actions — automated testing, image build, and K8s deployment on push
  • Message Broker: RabbitMQ cluster with mirrored queues for HA
  • Database: PostgreSQL per service (separate instances in production)
  • API Documentation: Swagger / OpenAPI auto-generated from Spring Boot annotations

10. Open Questions & Risk

Item Notes
Data Ownership Vehicle and offence data legally belongs to ZRP and ZINARA. Platform acts as operational source of truth pending formal data governance agreements.
ZINARA / VTS API Access Integration feasibility and data access agreements not yet confirmed. Dummy data used during development.
City Parking Sync City Parking system exists but API availability is unconfirmed.
Officer Adoption UX and offline capability are critical. If the mobile app is cumbersome, officers will not use it.
Cash Payment Integrity Cash payments recorded by officers carry corruption risk. Audit trail mitigates this. Supervisory approval step may be needed.
Regulatory Approval A government body must formally oversee the system before official deployment. Security requirements may change significantly.
Concurrent Users Expected load not yet estimated. Architecture is designed to scale; load testing benchmarks to be defined.
## Future Backlog
---
- ZIMRA integration — vehicle import duties and tax clearance
- Foreign vehicle handling — separate category and workflow
- Partial and instalment payments
- USSD interface — for users without smartphones
- WhatsApp notifications — additional notification channel
- National expansion — beyond Harare
- Insurance provider API integration
- Full regulatory compliance framework and data governance agreements
- Offline sync conflict resolution strategy for officer mobile app
- Database backup and point-in-time recovery
- Redis high availability — current single instance is a SPOF for the token blocklist
- Rate limiting on public auth endpoints