Skip to content

C4 — Containers

Deployable pieces inside CityCycle after the founding ADRs. The API is the Node.js process from ADR 0004. Battery telemetry storage from ADR 0003 is shown as a later addition.

C4Container
  title CityCycle — containers

  Person(rider, "Rider")
  Person(staff, "Operator / support")

  System_Boundary(citycycle, "CityCycle") {
    Container(mobile, "Mobile app", "iOS / Android", "Rider unlock and map")
    Container(console, "Operator console", "Web", "Fill levels and trip lookup")
    Container(api, "CityCycle API", "Node.js, Fastify", "Domain logic and integrations")
    ContainerDb(pg, "PostgreSQL", "Managed SQL", "Trips, inventory, payments")
    ContainerDb(redis, "Redis", "Managed cache", "Availability snapshot and unlock locks")
    ContainerDb(telemetry, "TimescaleDB", "Managed, second instance", "e-bike battery samples")
  }

  System_Ext(docks, "Dock network")
  System_Ext(payments, "Payment provider")
  System_Ext(idp, "Identity provider")

  Rel(rider, mobile, "Uses")
  Rel(staff, console, "Uses")
  Rel(mobile, api, "HTTPS / JSON")
  Rel(console, api, "HTTPS / JSON")
  Rel(api, pg, "Reads and writes")
  Rel(api, redis, "Reads and writes")
  Rel(api, telemetry, "INSERT battery_samples", "after ADR 0003")
  Rel(api, docks, "MQTT")
  Rel(api, payments, "HTTPS")
  Rel(api, idp, "OIDC")
---
config:
  layout: elk
---
flowchart TB
  rider["Rider"]
  staff["Operator / support"]

  subgraph citycycle["CityCycle"]
    mobile["Mobile app"]
    console["Operator console"]
    api["CityCycle API<br/>Node.js, Fastify"]
    pg[("PostgreSQL")]
    redis[("Redis")]
    telemetry[("TimescaleDB<br/>battery_samples")]
  end

  docks["Dock network"]
  payments["Payment provider"]
  idp["Identity provider"]

  rider --> mobile --> api
  staff --> console --> api
  api --> pg
  api --> redis
  api --> telemetry
  api --> docks
  api --> payments
  api --> idp