Architecture Decisions

ADR-001: Use Supabase as Backend-as-a-Service

Status: Accepted

Context: The platform needs a PostgreSQL database, authentication system, and real-time capabilities. Building and operating each of these independently increases operational complexity.

Decision: Use Supabase as an integrated backend platform providing managed PostgreSQL, authentication, and real-time subscriptions. File storage (images, documents) is handled separately by Google Cloud Storage (GCS) for tighter integration with Cloud CDN and the rest of the GCP ecosystem.

Consequences:

  • Reduced operational overhead — no need to manage database servers or auth infrastructure separately

  • File storage on GCS benefits from native Cloud CDN integration, fine-grained IAM controls, and consistent pricing within the GCP billing model

  • Built-in Row-Level Security simplifies authorization logic

  • Vendor dependency on Supabase, but PostgreSQL portability mitigates lock-in risk

  • Real-time subscriptions enable live property updates and notifications

ADR-002: Dual Map Provider Strategy (Google Maps + Mapbox)

Status: Accepted

Context: The platform requires geocoding, directions, distance calculations, and advanced map rendering with geofencing. No single provider excels at all requirements.

Decision: Use Google Maps for geocoding, directions, distance matrix, and Plus Code decoding. Use Mapbox for map rendering and geofencing capabilities.

Consequences:

  • Best-of-breed capabilities from each provider

  • Increased integration complexity — two map SDKs to maintain

  • Higher cost due to dual licensing, but optimized by using each for its strengths

  • Fallback capability — if one provider has issues, partial functionality remains

ADR-003: Cloud Run for Serverless Container Hosting

Status: Accepted

Context: The platform needs to scale dynamically to handle variable traffic loads while maintaining 99.999% availability, without the overhead of managing virtual machines.

Decision: Deploy both the NextJS frontend and Python backend as containerized services on Google Cloud Run.

Consequences:

  • Auto-scaling from zero handles traffic spikes efficiently

  • Pay-per-use pricing reduces cost during low-traffic periods

  • Cold start latency mitigated by minimum instance settings for critical paths

  • Container portability — services can be migrated to other platforms if needed

ADR-004: Workload Identity Federation for CI/CD Security

Status: Accepted

Context: The CI/CD pipeline deploys from both GitHub and Azure DevOps to GCP. Traditional approaches use service account keys, which create security risks if leaked.

Decision: Use Workload Identity Federation to authenticate GitHub Actions and Azure Pipelines with GCP without sharing service account credentials.

Consequences:

  • No long-lived credentials stored in CI/CD systems

  • Reduced attack surface — compromised CI/CD environments cannot extract permanent GCP credentials

  • More complex initial setup, but improved long-term security posture

  • Each platform (GitHub, Azure DevOps) federates independently with GCP

ADR-005: Windmill for Workflow Orchestration

Status: Accepted

Context: The platform requires complex multi-step workflows (property verification, payment processing, notification chains) that span multiple services and external integrations.

Decision: Use Windmill as the workflow orchestration engine for all backend business processes.

Consequences:

  • Visual workflow builder enables non-developer participation in workflow design

  • Built-in retry, error handling, and observability for long-running processes

  • Decouples workflow logic from application code

  • Adds an external dependency — Windmill must be available for background processes to function

ADR-006: NextJS with Server-Side Rendering

Status: Accepted

Context: Property listing pages must be indexable by search engines for organic traffic. The platform must also load quickly on mobile devices with varying network conditions common in Ghana and Africa.

Decision: Use NextJS with server-side rendering for property listing pages and static generation for informational pages.

Consequences:

  • Search engine optimization through SSR ensures property listings are discoverable

  • Faster initial page loads compared to client-side rendering

  • Increased server-side compute requirements for rendering

  • TypeScript provides type safety and improved developer experience

ADR-007: Single Load Balancer IP for Multi-Subdomain Architecture

Status: Accepted

Context: The platform uses multiple subdomains (www.asta.homes, api.asta.homes, admin.asta.homes). Each external IP address on GCP incurs cost.

Decision: Use a single Cloud Load Balancer with one external IP address to serve all asta.homes subdomains, using host-based routing rules to direct traffic to appropriate Cloud Run services.

Consequences:

  • Cost savings by consolidating IP addresses

  • Simplified DNS management — single IP for all subdomains

  • Single point of entry — load balancer becomes critical path (mitigated by GCP’s built-in HA for load balancers)

  • SSL certificates must cover all subdomains (wildcard certificate or individual certs)