egabriel.dev · tty1 · simulated boot (illustrative)
  1. GE-BIOS v2.6 · egabriel.dev portfolio platform
  2. CPU0: backend/cloud engineer · distributed systems
  3. Memory test: 16384M ... OK
  4. Boot device: static output · booting kernel
  5. [ 0.000000] portfolio-kernel 1.0 (static output) #1 SMP
  6. [ 0.018342] edge: HTTPS terminated at hosting provider[OK ]
  7. [ 0.041207] edge: security headers loaded[OK ]
  8. [ 0.052911] lsm: content-security-policy enforced (self + hashes)[OK ]
  9. [ 0.077915] fs: mounted version-controlled content[OK ]
  10. [ 0.112906] runtime: interactive components registered, loaded on demand[OK ]
  11. [ 0.163380] net: public API mapped at /api[OK ]
  12. [ 0.187004] api: contract published at /api/openapi.json[OK ]
  13. [ 0.201377] storage: no block device found (no database, by design)[SKIP]
  14. [ 0.224551] mail: contact delivery online[OK ]
  15. [ OK ]Started systems.service
  16. [ OK ]Started principles.service
  17. [ OK ]Started about.service
  18. [ OK ]Started resume.service
  19. [ OK ]Started contact.service
  20. [ OK ]Reached target portfolio (rack wall online)
Welcome...
Skip to content

Komuvo

Estate & community management platform: estate operations, residents, payments, visitors and communication.

Komuvo
Environment
Production SaaS
Primary constraint
Reliability + low operational cost
Architecture style
Modular application
Data
Relational
External dependencies
Payments · Notifications
My role
Architecture · Backend · Technical direction

01Overview

Komuvo runs the day-to-day operations of residential estates and gated business parks: who can enter, who has paid, and what needs fixing. It is a Scalefort product, and I led its architecture and backend.

02Problem

Estates need access verification for thousands of visitors, staff and residents every day. In suburban developments the telecom backhaul is intermittently unstable — and if the access service is down or lagging, vehicles queue onto public roads.

At the same time the platform collects service charges and utility payments across disjointed bank transfers. The ledger must be exact: no double-charging residents, no lost or unreconciled deposits.

03Constraints

  • Unreliable connectivity at the gate. Entry checks are validated by the server today, so working without a connection is the next goal.
  • Financial correctness. Every payment recorded exactly once, even when providers time out.
  • Low operational cost. A small team operating the system, on a modest hosting budget.

04My role

Architecture, backend engineering and technical direction — from module boundaries and data model to the reliability patterns described below.

05Architecture

A single application split into modules with enforced boundaries. Modules communicate through in-process interfaces and domain events; no module queries another module's tables directly. Select a component to see what it does and how it fails.

Component
Payment Providerexternal
Type
External payment API
Purpose
Processes resident payments.
Failure mode
Timeout / unavailable / ambiguous response.

06Engineering decisions

Visitor access

Residents create timed visitor passes. At the gate, guards check the QR code or PIN in the mobile app, the server validates it, and check-in is recorded as a separate step.

Offline gate verificationPLANNED

Not built yet. This is the intended design.

  1. When a resident creates a visitor pass, the server would sign a payload (timestamp, duration, estate) with a private key.
  2. Gate devices would cache the public keys and verify the signature locally, with no round-trip to the cloud API.
  3. Entry events would be spooled to local storage on a barrier controller and flushed to the backend once connectivity resumes.

Transactional outbox for side effects

An operation often has to save a record and send a message. Calling messaging providers inside the database transaction risks dual writes — the change commits but the notification throws. Instead, the change and an outbox message are written in the same transaction, and a background worker delivers the message.

begin transaction
  record the change
  record the outbox message
commit

# background worker delivers pending outbox messages

07Trade-offs & hindsight

What we chose

A modular application rather than independently deployed microservices.

Why we chose it

Microservices would have added RPC serialization, partial network failures and distributed sagas — failure modes the product had no requirement to take on.

What it gave us

One deployment to operate. Less infrastructure to maintain, and hosting that stayed under $40/month.

What it cost us

Read-heavy dashboards queried the same normalized tables the ledger wrote to. Past roughly 40 estates, end-of-month reconciliation caused database CPU spikes.

What I would change today

Introduce read replicas and materialized read models about six months earlier — while keeping the single deployment until operational requirements justify extracting a service.

08Reliability

Repeated payment requests
Payment requests carry idempotency keys, so a retry can't be recorded twice.
Payment provider degradationPLANNED
Not built yet. A circuit breaker would open after 5 failures in 30 seconds, and the API would return202 Accepted and fall back to webhook reconciliation instead of holding request threads.
Transient database failures
Transient database failures are retried automatically. If they still fail, the transaction rolls back cleanly.
Double-entry ledgerPLANNED
Not built yet. Today payments are kept as wallet and transaction records; a double-entry ledger would make every movement of money balance by construction.
Try a simulated payment failure in the Failure Lab →
← All systems