Architecture Decisions¶
ADR 1: Backend Technology Stack¶
Status:¶
Accepted (July 2025)
Context:¶
System needs robust backend technology for REST API and worker services. Team has existing familiarity with C# development.
Decision:¶
Use .NET 9 with C# for all backend services (REST API, MQTT Receiver, Weather Worker).
Alternatives Considered:¶
| Option | Pros | Cons |
|---|---|---|
| Node.js | Rapid iteration, huge ecosystem | Different stack; weaker static typing by default; less team experience |
| Go | High perf/concurrency; small binaries | Less team experience; different tooling |
| Python | Rich libs; fast prototyping | Lower throughput; weaker typing by default |
Consequences:¶
Positive:
- Team familiarity reduces development time
- Strong typing prevents runtime errors
- Excellent tooling and debugging support
- Modern async/await support for I/O operations
Negative:
- Platform dependency (though mitigated by containers)
- Larger memory footprint than some alternatives
Neutral:
- Containerization standardizes runtime
ADR 2: Microservices Architecture¶
Status:¶
Accepted (July 2025)
Context:¶
System has distinct responsibilities: API serving, MQTT message processing, and weather data fetching. Need modularity and independent scaling.
Decision:¶
Split backend into separate services: REST API, MQTT Receiver Worker, Weather Data Worker.
Alternatives Considered:¶
| Option | Pros | Cons |
|---|---|---|
| Monolith | Simple deploy; easy local dev | No independent scaling; fault blast radius |
| Modular monolith | Clear boundaries in one process | Still one deploy unit; limited isolation |
| Serverless | No servers to manage; auto-scale | Cold starts; platform coupling; ops visibility variance |
Consequences:¶
Positive:
- Clear separation of concerns
- Independent scaling and deployment
- Fault isolation between services
Negative:
- Increased deployment complexity
- Network communication overhead between services
Neutral:
- Requires basic observability to manage complexity
ADR 3: Dual Database Strategy¶
Status:¶
Accepted (July 2025)
Context:¶
System needs both structured application data (users, authentication) and time-series sensor data with different access patterns.
Decision:¶
Use PostgreSQL for application data and InfluxDB for time-series sensor data.
Alternatives Considered:¶
| Option | Pros | Cons |
|---|---|---|
| PostgreSQL + TimescaleDB | One stack; SQL everywhere | Ops complexity; perf tuning for time series needed |
| InfluxDB only | Optimized for time series | Awkward relational modeling; joins missing |
| SQLite + InfluxDB Lite | Simple, lightweight | Limited concurrency; feature gaps |
Consequences:¶
Positive:
- PostgreSQL optimized for relational data and transactions
- InfluxDB optimized for time-series queries and compression
- Each database serves its specific use case efficiently
Negative:
- Two databases to maintain and backup
Neutral:
- Extract, Transform, Load (ETL) between stores is minimal
ADR 4: Observability Stack¶
Status:¶
Accepted (July 2025)
Context:¶
Distributed microservices architecture requires comprehensive monitoring, logging, and alerting capabilities.
Decision:¶
Loki for logs, Prometheus for metrics, Grafana for dashboards, Alloy as agent.
Alternatives Considered:¶
| Option | Pros | Cons |
|---|---|---|
| ELK (Elasticsearch, Kibana) | Powerful search/analytics | Heavier footprint; more ops effort |
| OTel collector + vendor | Standards-based; flexible pipelines | Vendor lock-in and/or cost |
| Managed cloud observability | Minimal ops | Ongoing costs; data residency limits |
Consequences:¶
Positive:
- Complete observability into system health and performance
- Industry-standard tools with good integration
- Unified dashboard for all monitoring data
Negative:
- Additional infrastructure to maintain
Neutral:
- Can swap components later
ADR 5: Traefik as Reverse Proxy¶
Status:¶
Accepted (July 2025)
Context:¶
Multiple services need unified entry point, SSL termination, and service discovery in containerized environment.
Decision:¶
Use Traefik as reverse proxy with automatic service discovery and HTTPS termination.
Alternatives Considered:¶
| Option | Pros | Cons |
|---|---|---|
| Nginx | Mature; high performance | Manual routing/config; no auto-discovery |
| Caddy | Simple TLS; easy config | Fewer discovery features |
| HAProxy | Very fast; robust LB features | More manual config; fewer HTTP niceties |
Consequences:¶
Positive:
- Automatic service discovery via Docker labels
- Built-in SSL certificate management
- Load balancing capabilities
Negative:
- Single point of failure if not properly configured
- Additional configuration complexity
Neutral:
- Replaceable by Nginx if needed
ADR 6: JWT Authentication Strategy¶
Status:¶
Accepted (July 2025)
Context:¶
REST API requires secure authentication mechanism. Need stateless authentication for microservices architecture.
Decision:¶
Implement JWT token-based authentication with Entity Framework for user management.
Alternatives Considered:¶
| Option | Pros | Cons |
|---|---|---|
| Server-side sessions | Simple; revocation is trivial | Stateful; sticky sessions; scale limits |
| OAuth2/OIDC proxy | Standards-based; SSO ready | More moving parts; infra complexity |
| API keys | Simple; easy for machines | Poor granularity; rotation burdens |
Consequences:¶
Positive:
- Stateless authentication scales well
- Standard approach with good library support
- Tokens can carry user claims
Negative:
- Token revocation complexity
- Requires secure token storage on client side
Neutral:
- Token TTL balances risk and UX
ADR 7: Docker Compose for Development Environment¶
Status:¶
Accepted (July 2025)
Context:¶
Complex multi-service architecture needs consistent development environment setup across team members.
Decision:¶
Use Docker Compose to orchestrate all services for local development.
Alternatives Considered:¶
| Option | Pros | Cons |
|---|---|---|
| Dev Containers | Great DX; reproducible | Editor-coupled; learning curve |
| Kind/Minikube | Closer to k8s | Heavier locally; slower feedback |
| Scripts/Makefiles | Minimal tooling | Fragile; drift across machines |
Consequences:¶
Positive:
- Consistent development environment
- Easy service dependency management
- Simplified onboarding for new developers
Negative:
- Requires Docker knowledge from all developers
- Resource intensive on development machines
Neutral:
- Can migrate to Kubernetes later
ADR 8: Frontend¶
Status:¶
Accepted (July 2025)
Context:¶
System needs a frontend to display charts from measured/collected temperature data and to generate API docs with TypeDoc.
Decision:¶
v0
JavaScript React app via Docker. Reason: quick start.
Issue: Schema changes not caught at build time caused runtime UI errors (no static typing).
v1
TypeScript React with Create React App (CRA). Reason: typing and better tooling.
Issue: TypeDoc generation failed due to CRA/tooling version conflicts.
React + TypeScript built with Vite for the frontend.
Alternatives Considered:¶
| Option | Pros | Cons |
|---|---|---|
| CRA (TS) | Familiar, out-of-the-box setup | Tooling conflicts with TypeDoc |
| Next.js | SSR/ISR, ecosystem | Unneeded complexity for our use |
| Custom Webpack | Full control | More maintenance |
Consequences:¶
Positive:
- TypeDoc works
- faster startup
- lean tooling
Negative:
- Some devs must learn Vite
Neutral:
- No server-side rendering (SSR) required
ADR 9: Hardware Platform Decision (board, sensors)¶
Status:¶
Accepted (July 2025)
Context:¶
MKR1010 and ADT7410 were provided. Requirements: offline buffering, precise time, dual sites.
Decision:¶
Use Arduino MKR1010 with RTC DS3231 and SD card; deploy two identical units.
Alternatives Considered:¶
| Option | Pros | Cons |
|---|---|---|
| ESP32 boards | Wi-Fi integrated; strong community | Different toolchain; requalification |
| Different sensors | Potential accuracy/cost benefits | Revalidation effort; integration risk |
| Single hardware unit | Simpler setup | No north/south comparison; less robust |
Consequences:¶
Positive:
- Local data persistence via SD card enables offline data storage for ≤24h
- Timestamp reliability through RTC with battery
- Compact hardware, low power, WiFi-ready (MKR1010)
Negative:
- RTC and SD modules require additional wiring and SPI/I2C handling
- Time must be synchronized manually once (e.g., via compile-time setting or initial sync)
Neutral:
- The Arduino MKR1010 was predefined, not evaluated
- Final visualization and backend will depend on further platform choices (e.g., MQTT, REST, database)
ADR 10: Arduino Development Environment Decision¶
Status:¶
Accepted (July 2025)
Context:¶
Arduino firmware needs modular builds and host-side unit tests.
Decision:¶
PlatformIO for builds; Unity with native target for tests.
Alternatives Considered:¶
| Option | Pros | Cons |
|---|---|---|
| Arduino IDE | Easy; official | No native tests; inflexible structure |
| CMake toolchain | Flexible; IDE-agnostic | More setup; custom plumbing |
| Ceedling | Solid C test framework | Extra integration effort |
Consequences:¶
Positive:
- Reproducible builds and consistent project structure
- PC-native unit tests for business logic (Unity, native target)
- Seamless VS Code integration
- Use of modern C++ structure and dependency management
Negative:
- Additional setup effort for non-Arduino users (e.g., Unity, test runners)
- Developers must learn PlatformIO’s structure (src/lib/test)
Neutral:
- The PlatformIO toolchain abstracts away the underlying GCC setup
- Unit tests cannot cover board-specific behavior (e.g., Wire, SD, RTC) directly without mocks