ID: S202606091024
Status: imported

Tags: avans 2-4 LU1

AD: technologiestack voor de communicatiemodule

Context and Problem Statement

De communicatiemodule moet als zelfstandige SaaS-oplossing notificaties kunnen versturen voor meerdere OpenMRS-organisaties. De oplossing moet betrouwbaar, uitbreidbaar, veilig en goed te monitoren zijn. Daarnaast moet de module ook :

Voor deze ADR moeten keuzes worden gemaakt voor:

  1. Programmeertaal en framework
  2. Berichtenwachtrij
  3. Opslag
  4. Monitoringtooling

Voordat we een technologiestack kiezen, moeten we eerst in kaart brengen welke eisen uit de opdracht technisch het belangrijkst zijn. Deze eisen vertalen we vervolgens naar concrete technische behoeften. Op basis daarvan kunnen we onderbouwen welke programmeertaal, framework, berichtenwachtrij, opslagoplossing en monitoringtooling het beste passen.

Decision Drivers

De belangrijkste eisen die deze keuze sturen zijn:

  1. De communicatiemodule moet als zelfstandige service kunnen draaien.
    Dus is een framework nodig dat geschikt is voor een stand-alone backend-service.
  2. Notificaties moeten 24 uur en 1 uur vooraf verstuurd kunnen worden.
    Dus is ondersteuning voor scheduling of background processes belangrijk.
  3. Providerstoringen moeten worden opgevangen met retry/fallback.
    Dus is een betrouwbare queue of broker logisch.
  4. De module moet veilig en betrouwbaar configuratie, status en metadata opslaan.
    Dus ligt een relationele database voor de hand liggend.
  5. De werking moet inzichtelijk zijn via monitoring en een dashboard.
    Dus is observability tooling nodig.
  6. De stack moet haalbaar zijn voor ons team.
    Dus wegen bestaande teamkennis, eenvoud, documentatie en integratiegemak ook mee.

Shortlist rationale

We hebben de shortlist niet willekeurig samengesteld. We hebben eerst gekeken naar de belangrijkste eisen van de opdracht, en daarna per categorie bekeken welke opties daar logisch op aansluiten.

Voor programmeertaal en framework hebben we gekeken naar technologieën die geschikt zijn voor een zelfstandige backend-service, geplande taken ondersteunen en goed passen bij een API-gebaseerde architectuur. Daardoor kwamen Java + Spring Boot, C# + .NET, Node.js + Express en Rust naar voren als logische opties om te vergelijken.

Voor de berichtenwachtrij hebben we gekeken naar opties die retry/fallback en asynchrone verwerking ondersteunen. Daarom hebben we RabbitMQ als serieuze optie meegenomen. Een volledig zelfgemaakte queue vonden we minder logisch, omdat we dan zelf veel foutafhandeling en betrouwbaarheid zouden moeten bouwen.

Voor opslag hebben we gekeken naar databases die goed passen bij gestructureerde gegevens, zoals organisaties, afspraken, notificaties en statussen. Daarom hebben we vooral relationele databases meegenomen, met MariaDB als voorkeursrichting.

Voor monitoring hebben we gekeken naar tooling die goed past bij een service die inzichtelijk moet zijn via statusinformatie, foutmeldingen, metrics en tracing. Daarom hebben we gekozen om OpenTelemetry als observability-oplossing mee te nemen.

Naast technische geschiktheid hebben we ook meegewogen of een optie voor ons team haalbaar is binnen de tijd van het project. Daardoor is de shortlist gebaseerd op een combinatie van opdrachtvereisten, technische logica en praktische uitvoerbaarheid.


Considered Options

Option 1

Java + Spring Boot, RabbitMQ, MariaDB, OpenTelemetry

Option 2

C# + .NET 10, RabbitMQ, MariaDB, OpenTelemetry

Option 3

Node.js + Express, zelfgemaakte of externe queue, MongoDB of MariaDB, zelfgemaakte monitoring of OpenTelemetry-stack


Decision consequences

Option 1

Good, because:

  • Spring Boot past goed bij een zelfstandige backend-applicatie.
  • Spring ondersteunt scheduling, wat goed aansluit op notificaties die 24 uur en 1 uur van tevoren verstuurd moeten worden.
  • In combinatie met RabbitMQ, MariaDB en OpenTelemetry is dit technisch een bruikbare stack voor deze opdracht.

Neutral, because:

  • Deze optie past inhoudelijk goed bij de opdracht.
  • Ook deze stack zou gebruikt kunnen worden om een zelfstandige communicatieservice te bouwen.

Bad, because:

  • Deze optie sloot minder goed aan op wat wij als team al kennen.
  • We liepen ook tegen praktische problemen aan met de beschikbare Spring Boot templates en de Java-versie die wij wilden gebruiken.
    Daardoor vonden wij deze optie minder haalbaar binnen onze projectscope, ook al is het technisch verdedigbaar.

Option 2

Good, because:

  • .NET 10 past goed bij het bouwen van een zelfstandige backend-service.
  • Binnen .NET kunnen we dependency injection gebruiken, wat helpt om onderdelen van de applicatie netjes samen te laten werken.
  • Binnen .NET kunnen we ook background tasks gebruiken, wat goed past bij notificaties die op vaste momenten verstuurd moeten worden.
  • RabbitMQ past goed bij onze opdracht, omdat het werkt met wachtrijen voor berichten en helpt bij retry/fallback en foutafhandeling.
  • MariaDB past goed bij onze opdracht, omdat we werken met gestructureerde gegevens zoals organisaties, afspraken, notificaties en statussen.
  • OpenTelemetry past goed bij de monitoringeisen, omdat het gebruikt kan worden voor traces, metrics en logs. Deze stack sluit voor ons beter aan op de kennis die we al hebben, waardoor wij de oplossing realistischer kunnen bouwen en uitleggen.

Neutral, because:

  • Deze stack bestaat uit meerdere onderdelen, zoals een backend, een broker, een database en observability-tooling.
  • Dat is niet meteen een nadeel, maar het betekent wel dat we meer onderdelen moeten configureren en met elkaar moeten laten samenwerken.
  • De oplossing wordt daardoor uitgebreider dan een klein prototype.

Bad, because:

  • Ook met deze stack moeten we nog uitzoeken hoe RabbitMQ, MariaDB en OpenTelemetry precies samen in onze oplossing passen.
  • Daarnaast vraagt observability met OpenTelemetry meer inrichting dan alleen eenvoudige logging. De stack past goed bij de opdracht, maar blijft groter dan een minimale proof of concept.

Option 3

Good, because:

  • Node.js is gemaakt voor schaalbare netwerkapplicaties.
  • Express maakt het makkelijk om snel een API op te zetten.
    Daardoor is deze optie aantrekkelijk als we snel iets werkends willen neerzetten.

Neutral, because:

  • Node.js en Express kunnen gebruikt worden voor deze opdracht.
  • Wel moeten we dan meer keuzes zelf maken over de structuur van de applicatie.
  • Ook zaken zoals scheduling, achtergrondverwerking en de opbouw van de architectuur moeten we dan meer zelf regelen.

Bad, because:

  • Deze optie legt meer verantwoordelijkheid bij ons team om zelf een goede structuur neer te zetten.
  • Wij moeten dan zelf meer keuzes maken over foutafhandeling, uitbreidbaarheid en de inrichting van de applicatie.
    Daardoor vonden wij deze optie minder goed passend bij de eisen van deze opdracht.

Decision Outcome

Gekozen: Option 2 — C# + .NET 10, RabbitMQ, MariaDB, OpenTelemetry

More information

Bij deze ADR hebben we vooral gekeken naar:

  • Documentatie over background tasks en dependency injection in .NET 10.
  • Documentatie over queues en foutafhandeling in RabbitMQ.
  • Documentatie over transacties en relationele opslag in MariaDB.
  • Documentatie over traces, metrics en logs in OpenTelemetry.

Sources

SpringBoot: