---
{
  "title": "Performance at Scale: Baseline",
  "description": "Ein Ausgangspunkt für unsere Serie zu Performance at Scale: Was wir zuerst messen, warum der Startpunkt wichtig ist und wie wir den Benchmark fair gestalten.",
  "date": "2026-06-29",
  "author": "Marat Surmashev",
  "reading-time": "6 min read",
  "tags": ["Database", "Infrastructure", "Aidbox", "Performance"]
}
---

## Warum der Ausgangspunkt wichtig ist

Bevor wir FHIR-Server unter Last vergleichen, benötigen wir einen sauberen Ausgangspunkt. Der Baseline zeigt uns, wie sich die Systeme bei einer leeren (oder nahezu leeren) Datenbank verhalten, und liefert uns eine Referenz für alles, was später folgt – wenn Datenvolumen und Traffic zunehmend eine Rolle spielen.

Wie in unserem [vorherigen Beitrag](/articles/performance-at-scale) erläutert, konzentrieren wir uns auf die grundlegenden FHIR-Workloads: CRUD, Bundle-Verarbeitung und Suche. Der gesamte Benchmark ist **Open Source** – der Quellcode, das Test-Framework und die Ergebnisse befinden sich alle in [github.com/HealthSamurai/fhir-server-performance-benchmark](https://github.com/HealthSamurai/fhir-server-performance-benchmark), und der Lauf wird täglich neu ausgeführt, sodass der [interaktive Bericht](https://healthsamurai.github.io/fhir-server-performance-benchmark/) (jedes Diagramm plus die Rohdaten) stets die aktuellen Zahlen widerspiegelt. Die in diesem Beitrag zitierten Zahlen stammen aus dem Lauf vom 28. Juni 2026; der Live-Bericht ist die maßgebliche Quelle.

Wir testen vier FHIR-Server: Aidbox, HAPI FHIR, Medplum und den Microsoft FHIR Server. Sie umspannen drei verschiedene Laufzeitumgebungen und zwei verschiedene Datenbanken. Aidbox und HAPI laufen beide auf der JVM mit PostgreSQL; Medplum läuft auf Node.js, ebenfalls mit PostgreSQL; und der Microsoft FHIR Server läuft auf .NET und ist beim Speicher die Ausnahme – er unterstützt kein PostgreSQL, weshalb wir die neueste Version des Microsoft FHIR Servers auf SQL Server betreiben.

| Server | Code-Basis     | Laufzeit        | Datenbank     |
|--------|---------------|----------------|-------------|
| [Aidbox](https://www.health-samurai.io/fhir-server)    | Closed Source | JVM (Clojure) | PostgreSQL  |
| [HAPI FHIR](https://github.com/hapifhir/hapi-fhir)  | Open Source | JVM (Java)     | PostgreSQL  |
| [Medplum](https://github.com/medplum/medplum)    | Open Source | Node.js        | PostgreSQL  |
| [Microsoft FHIR Server](https://github.com/microsoft/fhir-server)    | Open Source | .NET (C#)      | SQL Server  |

Der Microsoft FHIR Server ist die neueste Ergänzung des Benchmarks, und die nachfolgenden Ergebnisse schließen ihn nun gemeinsam mit den drei PostgreSQL-basierten Servern ein.


## Testumgebung

Unsere Tests laufen auf einem einzigen Bare-Metal-Rechner mit 64 CPU-Kernen und 500 GB RAM. Der gesamte Stack wird mit Docker Compose orchestriert, und Ressourcen sind pro Container fixiert, damit der Vergleich fair bleibt:

| Server | Image | CPU / RAM | Topologie |
|--------|-------|-----------|----------|
| Aidbox | `healthsamurai/aidboxone:edge` | 8 vCPU / 24 GB | Einzelinstanz (JVM) |
| HAPI FHIR | `hapiproject/hapi:latest` | 8 vCPU / 24 GB | Einzelinstanz (JVM) |
| Medplum | `medplum/medplum-server:latest` | 1 vCPU / 3 GB je Instanz | 8 Replikate (Node.js) |
| Microsoft FHIR Server | `mcr.microsoft.com/healthcareapis/r4-fhir-server:latest` | 8 vCPU / 24 GB | Einzelinstanz (.NET) |

Jeder Anwendungsserver erhält dasselbe Budget: 8 vCPU und 24 GB RAM. Medplum erreicht dies auf anderem Weg – seine Node.js-Laufzeitumgebung ist single-threaded, sodass ein einzelner Prozess keine 8 Kerne nutzen kann; der Server wird daher als 8 Replikate mit je 1 vCPU / 3 GB skaliert (insgesamt 8 vCPU und 24 GB), um unter gleichen Bedingungen anzutreten. Medplum benötigt zusätzlich Redis für Sitzungen und Caching, was die anderen Server nicht erfordern.

Für die drei PostgreSQL-basierten Server bildet **PostgreSQL 18** (8 vCPU / 30 GB) die Datenbankschicht, die über den gesamten Stack gemeinsam genutzt, jedoch durch ein Datenbankmodell pro Server isoliert wird, sodass der Speicher oder die Abfragelast eines Servers die anderen nicht beeinflusst. Der Microsoft FHIR Server kann nicht auf PostgreSQL betrieben werden und erhält daher seinen eigenen dedizierten **SQL Server 2022** (Developer Edition) mit demselben Budget von 8 vCPU / 30 GB – das SQL-Server-Pendant zum gemeinsam genutzten Postgres. Da die Suiten sequenziell ausgeführt werden, ist jeweils nur ein Anwendungsserver und seine Datenbank aktiv. Alles läuft auf lokalem NVMe-SSD-Speicher, um Netzwerklatenz aus den Ergebnissen zu eliminieren und den Datensatz nahe am Server zu halten.

Für die Lastgenerierung verwenden wir [Grafana k6](https://k6.io/), das die Szenarien sequenziell ausführt (Vorwärmphase → CRUD → Import → Suche). Für synthetische Daten setzen wir [Synthea](https://github.com/synthetichealth/synthea) ein, da es realistische Muster von Gesundheitsdaten erzeugt. CPU-, Speicher- und I/O-Daten pro Container werden mit cAdvisor erfasst, während Datenbank-Interna von postgres-exporter (für die PostgreSQL-Server) und mssql-exporter (für den SQL Server des Microsoft FHIR Servers) stammen. All diese Daten werden von Prometheus aggregiert und in Grafana visualisiert – dieselben Metriken, die den nachfolgenden Diagrammen zugrunde liegen. Vollständige Details finden sich auf der [Infrastrukturseite](https://healthsamurai.github.io/fhir-server-performance-benchmark/infrastructure/) des Berichts.

> **Ein Hinweis zur Fairness.** Wir entwickeln Aidbox und kennen ihn daher naturgemäß am besten. Wir sind *keine* Experten für HAPI FHIR, Medplum oder den Microsoft FHIR Server, und es ist durchaus möglich, dass unsere Konfiguration für diese Server nicht optimal ist. Unser Ziel war das Gegenteil von selektiver Auswahl: die Hardware-Auslastung maximieren und jedem Server möglichst gleiche Ressourcen zur Verfügung stellen. Das gesamte Setup ist aus genau diesem Grund Open Source – wenn Sie wissen, wie einer dieser Server besser konfiguriert werden kann, würden wir das gerne erfahren. Eröffnen Sie ein Issue oder einen Pull Request im [Benchmark-Repository](https://github.com/HealthSamurai/fhir-server-performance-benchmark), und der tägliche Lauf wird Ihre Änderungen übernehmen.

## Test-Suiten und Szenarien

Performance-Tests sind entscheidend, um das Systemverhalten unter Last zu verstehen. Für diesen Baseline-Test führen wir drei Suiten in dieser Reihenfolge aus:

1. **CRUD auf einer leeren Datenbank**
   - Messung der Create-, Read-, Update- und Delete-Performance bei einer frischen Installation
2. **Batch-Import (1.000 Patienten)**
   - Durchführung eines Batch-Imports von 1.000 synthetischen (Synthea) Patientendatensätzen sowie Messung von Durchsatz und Speicherbedarf
3. **Suche**
   - Bewertung der Such-Performance gegen den importierten Datensatz

Dies liefert uns einen sauberen Referenzpunkt. Größere Datensätze und inkrementelle Last – bei denen Schreibdegradierung und komplexe Abfragen zunehmend relevant werden – sind Gegenstand der nächsten Beiträge in dieser Serie.

## Baseline-CRUD-Performance

Die CRUD-Suite enthält sequenzielle Create-, Read-, Update- und Delete-Operationen über neun verschiedene FHIR-Ressourcen: Patient, Location, Practitioner, Organization, Encounter, MedicationRequest, Observation, Claim und ExplanationOfBenefit. Die Suite läuft mit konstant 300 parallelen Threads für bis zu 5 Minuten.

Wir ermitteln Baseline-Metriken anhand des durchschnittlichen RPS über alle Iterationen.

__Durchschnittlicher Durchsatz (RPS) über alle CRUD-Operationen (höher ist besser)__
![CRUD operations RPS on empty database](total_rps.svg)

| Server | Gesamter CRUD-Durchsatz (RPS) |
|--------|-----------------------------|
| Aidbox | 5.212 |
| HAPI   | 3.058 |
| Medplum | 1.420 |
| Microsoft FHIR Server | 440 |

__Durchschnittliche Latenz (99. Perzentil) nach Operation (niedriger ist besser)__
![CRUD operations p99 latency by operation](describe_rps.svg)

| Operation | Aidbox | HAPI | Medplum | Microsoft |
|-----------|--------|------|---------|-----------|
| Create | 106 ms | 276 ms | 758 ms | 1.180 ms |
| Read   | 91 ms | 225 ms | 404 ms | 379 ms |
| Update | 110 ms | 271 ms | 626 ms | 1.233 ms |
| Delete | 93 ms | 239 ms | 647 ms | 1.064 ms |

Auf Basis dieser Ergebnisse liefert Aidbox etwa 70 % mehr Durchsatz als HAPI und rund 3,7-mal mehr als Medplum. Der Microsoft FHIR Server liegt in dieser Suite weit zurück bei 440 RPS – mehr als eine Größenordnung unterhalb von Aidbox. Bei der Latenz ist Aidbox beim 99. Perzentil etwa 2,5-mal schneller als HAPI und 6-mal schneller als Medplum. Der Microsoft FHIR Server ist ein interessanter Fall: Seine Lesevorgänge sind schnell (379 ms p99, sogar vor Medplum), aber seine Schreibvorgänge sind die langsamsten der Gruppe (~1,2 s p99 bei Create und Update), was seinen Gesamtdurchsatz nach unten zieht.

Ein wichtiger Hinweis beim Lesen dieser Zahlen: Die Durchsatz-Differenz (≈70 % gegenüber HAPI) ist geringer als die Latenz-Differenz (≈2,5-fach). Unter hoher Parallelität kann ein Server den Gesamtdurchsatz aufrechterhalten, indem er viele Anfragen gleichzeitig verarbeitet, auch wenn jede einzelne Anfrage langsamer ist. Daher bewegen sich Tail-Latenz und Gesamt-RPS nicht zwingend parallel – ein Einzelzahlvergleich kann verbergen, welcher Aspekt für eine bestimmte Arbeitslast tatsächlich entscheidend ist.

__Durchschnittliche Latenz über alle Operationen (99. Perzentil) nach Ressourcengröße (niedriger ist besser)__
![CRUD p99 latency by resource size](avg_latency_by_resource_size.svg)

Das Diagramm zeigt, dass Aidbox eine leichte Korrelation zwischen Latenz und Ressourcengröße aufweist, die am deutlichsten bei der Verarbeitung von Encounter-, Patient- und ExplanationOfBenefit-Ressourcen erkennbar ist. HAPI zeigt über verschiedene Ressourcengrößen eine gleichmäßigere Latenz, während Medplum und der Microsoft FHIR Server bei Schreibvorgängen einheitlich hohe Werte aufweisen. Wir beobachten zudem einen interessanten Ausreißer bei der Patient-Verarbeitung durch Medplum (sein Create-p99 springt auf ~1,16 s, gegenüber ~560–830 ms bei anderen Ressourcen), was darauf hindeutet, dass für die Patient-Ressource spezifisch zusätzliche Verarbeitungsschritte stattfinden.

## Batch-Verarbeitung

Zur Prüfung der Batch-Verarbeitungskapazitäten verwendeten wir einen Datensatz von 1.000 synthetischen Patientendatensätzen, die mit Synthea generiert wurden (insgesamt rund 2 Millionen Ressourcen). Die generierten FHIR-Bundles variieren in der Größe, von kleinen Bundles mit etwa 150 KB bis hin zu großen mit bis zu 120 MB und bis zu 50.000 Ressourcen in einem einzelnen Bundle. Jedes Bundle hat den Typ `transaction`. Um den Test realistischer und praxisnäher zu gestalten, haben wir 20 parallele Threads zur Verarbeitung dieser Bundles eingesetzt.

__Durchschnittlicher Durchsatz (Ressourcen pro Sekunde) nach Server (höher ist besser)__
![1,000 synthetic patient records import throughput](1k_import_throughput.svg)

| Server | Import-Durchsatz (Ressourcen/Sek.) |
|--------|-----------------------------------|
| Aidbox | 2.678 |
| HAPI   | 2.214 |
| Medplum | 764 |
| Microsoft FHIR Server | 448 |

Bei der Batch-Verarbeitung führen Aidbox und HAPI und wechseln sich zwischen den Läufen an der Spitze ab – in diesem Lauf liegt Aidbox vorne und verarbeitet 2.678 Ressourcen pro Sekunde gegenüber HAPIs 2.214 (etwa 21 % schneller). Medplum liegt mit 764 Ressourcen pro Sekunde deutlich hinter beiden, und der Microsoft FHIR Server ist mit 448 Ressourcen pro Sekunde der langsamste – ungefähr 5–6-mal langsamer als die beiden JVM-Server.

__Datenbankgröße nach Server (niedriger ist besser)__
![1,000 synthetic patient records import database size](1k_import_db_size.svg)

Beim Speicherbedarf spreizen sich die vier Server am stärksten auf, in zwei grobe Lager. Der Microsoft FHIR Server (4,24 GB) und Aidbox (6,83 GB) bleiben kompakt; Medplum (11,8 GB) und HAPI (22,6 GB) sind deutlich größer – HAPIs Footprint ist etwa 3,3-mal so groß wie der von Aidbox. Die zwei kompakten Server erreichen dies auf unterschiedliche Weise: Aidbox dadurch, dass keine Indizes vorab aufgebaut werden, der Microsoft FHIR Server durch seinen SQL-Server-Datenspeicher – allerdings zahlt der Microsoft-Server dafür, wie oben gesehen, anderswo seinen Preis, nämlich bei langsamen Schreibvorgängen und Suchen. Auf den Index-Kompromiss gehen wir im Fazit noch einmal ein.

## Such-Suite

Das umfassende Benchmarking der Suchfunktionalität in einem FHIR-Server ist aus mehreren Gründen eine komplexe Aufgabe:

1. FHIR verfügt über eine umfangreiche Menge an Suchparametern, was einen vollständigen Benchmark zeitaufwendig macht.
2. Es gibt viele Kombinationen aus Suchparametertyp und Wertetyp.
3. Auf Suchen können verschiedene Modifier und Präfixe angewendet werden.
4. Es gibt komplexe Operationen wie Joins (`_include`, `_revinclude`, `_has`, verkettete Suchen) und Sortierung.
5. Die Anzahl möglicher Suchparameter-Kombinationen ist enorm.

Da das Testen jeder möglichen Suchparameter-Kombination unpraktikabel ist, konzentrieren wir uns auf die am häufigsten verwendeten Suchparameter. Dies liefert uns ein solides Basisverständnis davon, wie effizient jeder Server seine Suchlogik implementiert. Wir konzentrieren uns auf Standard-FHIR-R4-Suchparameter, die in der Praxis häufig verwendet werden und für die entsprechende Daten in unserem synthetischen Datensatz vorhanden sind – und decken dabei sechs Familien ab: String, Datum, Referenz, Quantity, Token und FHIR-Composite-Parameter.

Wir führen die Suite mit 30 parallelen Threads (k6-VUs) für 2 Minuten aus und verwenden eine feste Seitengröße von 20 Ergebnissen (`_count=20`). Da Suchoperationen große Ergebnismengen zurückgeben können, schließen wir die Übertragungszeit und das Parsing der Antwort von den Messungen aus, indem wir die k6-Einstellung `discardResponseBodies: true` aktivieren – wir konzentrieren uns ausschließlich auf die Server-Antwortzeit, nicht auf FHIR-Konformität. Alle Suchfamilien laufen gemischt in einer einzigen Iteration statt sequenziell, was dem realen Einsatz näherkommt. Jede Familie sendet zudem einen absichtlich nicht treffenden Wert (eine nicht existierende ID, einen Code oder einen Namen), um den Pfad bei leeren Ergebnissen zu prüfen, und Referenzwerte werden unmittelbar vor dem Lauf live von jedem Server (echte Ressourcen-IDs) abgerufen.

Ein Vorbehalt ergibt sich aus dem Verwerfen der Antwort-Bodies: Wir messen die Antwortzeit, nicht die Korrektheit. Ein Server, der einen Anfragetyp fehlerhaft behandelt – indem er schnell einen Fehler oder ein ungefiltertes Ergebnis zurückgibt – kann künstlich schnell wirken. Wir kennzeichnen den einen Fall, den wir gefunden haben (Medplums Composite-Suche, siehe unten), aber dieselbe Skepsis gilt generell: Behandeln Sie jede ungewöhnlich niedrige Latenz für einen bestimmten Server und Typ als etwas, das anhand der Live-Ergebnisse überprüft werden sollte, anstatt es für bare Münze zu nehmen.

Die von uns geprüften Parameter:

| Suchtyp | Ressource | Parameter |
|-------------|----------|------------|
| String | Patient | `name`, `address` (mit `:contains`) |
| String | Organization | `name` (mit `:contains`) |
| Datum | Patient | `birthdate` |
| Datum | Observation | `date` |
| Datum | Encounter | `date` |
| Referenz | Observation | `subject`, `encounter`, `performer` |
| Referenz | Encounter | `subject`, `participant` |
| Referenz | MedicationRequest | `subject`, `encounter`, `requester` |
| Quantity | Observation | `value-quantity`, `component-value-quantity`, `combo-value-quantity` |
| Token | Observation | `category`, `code` |
| Token | Encounter | `status`, `class` |
| Composite | Observation | `code-value-quantity`, `component-code-value-quantity`, `combo-code-value-quantity` |

Datums- und Quantity-Suchen wechseln durch Präfixe (`eq`, `lt`, `gt`, `ge`, `le`; Datumssuchen ergänzen zusätzlich `sa` und `eb`). String-Suchen verwenden den `:contains`-Modifier. Token-Suchen umfassen einfaches `[code]`, vollqualifiziertes `[system]|[code]` sowie kommagetrennte ODER-Listen. Composite-Suchen verwenden FHIR-Composite-Parameter mit dem `$`-Separator (zum Beispiel `code-value-quantity=8867-4$gt100`).

### Suchergebnisse

__Gesamter Such-Durchsatz (RPS, höher ist besser)__
![Search throughput by server](search_throughput.svg)

| Server | Such-Durchsatz (RPS) |
|--------|-------------------------|
| Aidbox | 3.404 |
| Medplum | 1.796 |
| HAPI   | 1.005 |
| Microsoft FHIR Server | 261 |

__P99-Latenz nach Suchtyp (ms, niedriger ist besser)__
![Search p99 latency by type](search_latency.svg)

| Suchtyp | Aidbox | Medplum | HAPI | Microsoft |
|-------------|--------|---------|------|-----------|
| String    | 24 | 81 | 77  | 188 |
| Datum      | 26 | 82 | 121 | 271 |
| Referenz | 24 | 83 | 96  | 167 |
| Token     | 32 | 82 | 97  | 197 |
| Quantity  | 55 | 91 | 101 | 1.191 |
| Composite | 47 | — | 125 | 1.897 |

*Das Diagramm zeigt alle vier Server. Die p99-Werte des Microsoft FHIR Servers bei Quantity (~1,2 s) und Composite (~1,9 s) sprengen die Skala und drücken die drei PostgreSQL-Server zu kurzen Balken nahe der Basislinie zusammen – die genauen Werte finden sich in der Tabelle oben. Medplum fehlt in der Composite-Gruppe, da dieser Suchtyp nicht unterstützt wird (siehe unten).*

Die Reihenfolge ändert sich im Vergleich zu CRUD. Bei der Suche führt Aidbox den Durchsatz mit 3.404 RPS an – etwa 90 % mehr als Medplum (1.796 RPS) und rund 3,4-mal mehr als HAPI (1.005 RPS). Der Microsoft FHIR Server liegt mit 261 RPS weit zurück. Bemerkenswert ist, dass HAPI – der bei CRUD noch auf dem zweiten Platz lag – bei der Suche der langsamste der drei PostgreSQL-Server ist, sowohl beim Durchsatz als auch bei der Tail-Latenz.

Bei der Latenz erzielt Aidbox bei jeder Suchfamilie den niedrigsten p99-Wert. Medplum liegt durchgehend im Mittelfeld – mit Ausnahme der Composite-Suche, die nicht unterstützt wird (siehe den Hinweis unten). Unter den Postgres-Servern ist HAPIs Latenz die höchste und bewegt sich über die Familien hinweg zwischen etwa 95 und 125 ms. Der Microsoft FHIR Server befindet sich in einer völlig anderen Größenordnung: Bei String-, Datums-, Referenz- und Token-Suchen tolerierbar (~170–270 ms), aber extrem langsam bei Quantity- (~1,2 s) und Composite-Suchen (~1,9 s) – genau das ist es, was seinen Such-Durchsatz so niedrig hält.

> **Medplum unterstützt keine Composite-Suche.** Medplums [Dokumentation zur Sucharchitektur](https://www.medplum.com/docs/contributing/search-architecture) listet den FHIR-`composite`-Parametertyp als nicht unterstützt auf. Im Benchmark kehren diese Anfragen zurück, ohne dass die Suche ausgeführt wird; daher ist jede dabei gemessene Latenz oder jeder Durchsatz ein Artefakt und keine echte Messung – weshalb Medplum in früheren Entwürfen bei Composite-Suchen scheinbar „alle übertraf". Wir lassen daher Medplums Composite-Zelle leer und schließen ihn aus dem Diagramm aus. Die Quantity-Suche hingegen *wird* von Medplum unterstützt, sodass diese Zahlen gültig sind.

Ein Hinweis zum Umfang: Dieser Baseline-Test schließt keine Sortierung (`_sort`) oder Join-Operationen (`_include`, `_revinclude`, `_has`, verkettete Suchen) ein. Diese sind erst bei zunehmendem Datenvolumen besonders aussagekräftig – bei einem Datensatz mit 1.000 Patienten passt fast alles in den Speicher –, weshalb wir sie bei größeren Datensätzen in einem späteren Beitrag ergänzen.

## Fazit

Auf einem sauberen, größtenteils im Speicher gehaltenen Baseline sieht die Rangfolge wie folgt aus – sie verschiebt sich leicht zwischen den täglichen Läufen, daher sind diese Ergebnisse als Momentaufnahme zu verstehen, nicht als endgültiges Urteil:

- **CRUD** — Aidbox führt beim Durchsatz (5.212 RPS) vor HAPI (3.058) und Medplum (1.420) und weist bei jeder Operation die beste p99-Latenz auf (~100 ms gegenüber ~250 ms für HAPI und ~610 ms für Medplum). Der Microsoft FHIR Server liegt mit 440 RPS zurück, mit schnellen Lesevorgängen, aber ~1,2 s Schreiblatenz.
- **Batch-Import** — Aidbox führt die Ingestion in diesem Lauf an (2.678 gegenüber HAPIs 2.214 Ressourcen/Sek.); Medplum liegt deutlich dahinter (764), und der Microsoft FHIR Server ist am langsamsten (448).
- **Suche** — Aidbox führt sowohl beim Durchsatz (3.404 RPS) als auch bei der Latenz pro Abfrage; HAPI fällt unter den Postgres-Servern auf den letzten Platz, und der Microsoft FHIR Server liegt beim Durchsatz (261 RPS) weit zurück, bedingt durch sehr langsame Quantity- und Composite-Abfragen.
- **Speicher** — Zwei Lager: Der Microsoft FHIR Server (4,24 GB) und Aidbox (6,83 GB) sind kompakt, während Medplum (11,8 GB) und HAPI (22,6 GB) größer sind – HAPIs Footprint ist etwa 3,3-mal so groß wie der von Aidbox.

### Indexierungsstrategie: ein Kompromiss, den dieser Baseline nur halb misst

Die Speicher- und Import-Zahlen folgen direkt daraus, wie jeder Server Daten speichert und indiziert – und diese Entscheidung ist ein Kompromiss, kein Urteil.

HAPI, Medplum und der Microsoft FHIR Server bauen beim Schreiben von Daten vorab Indizes auf durchsuchbaren Feldern auf. Das kostet Schreibdurchsatz, und bei HAPI und Medplum auch Speicherplatz (die oben genannten 12–23 GB). Der Microsoft FHIR Server zeigt, dass die Speicherkosten nicht unvermeidlich sind – er baut Indizes vorab auf und bleibt trotzdem bei 4,24 GB –, zahlt dafür aber stark bei der Schreiblatenz.

Aidbox wählt den entgegengesetzten Standard, was beide Seiten hat. Es werden standardmäßig **keinerlei Suchindizes** ausgeliefert – das macht seine Imports schnell und seinen Footprint klein, bedeutet aber auch, dass eine unindizierte Abfrage auf einen Sequential Scan zurückfällt und die Verantwortung für die Indizierung auf Sie übergeht. Das ist keine triviale Aufgabe: Sie müssen wissen, welche Suchparameter Ihre Arbeitslast tatsächlich nutzt, und eine übermäßige Indizierung bringt genau die Schreib- und Speicherkosten zurück, die wir gerade beschrieben haben. Was Aidbox anstelle vorgebauter Indizes bietet, ist das Werkzeug, dies gezielt umzusetzen – Query-Analysen, Statistiken dazu, welche Suchparameter tatsächlich verwendet werden, und Index-Empfehlungen, die aus dem realen Traffic abgeleitet werden. Richtig eingesetzt ermöglicht dies eine präzise Indizierung für Ihre Arbeitslast mit sowohl schnellen Operationen als auch einem sehr kompakten, effizient gespeicherten Datensatz; bei sorglosem Einsatz erhalten Sie einen Server ohne Indizes. Das ist ein leistungsfähigerer Standard in erfahrenen Händen und eine schärfere Kante in unerfahrenen.

Der wichtige Vorbehalt – und der Grund, die obigen Such-Zahlen aufmerksam zu lesen – ist, dass das Voraufbauen von Indizes etwas bietet: vorhersehbare Abfrage-Performance beim Datenwachstum. Ein Datensatz mit 1.000 Patienten, der problemlos in den Speicher passt, ist genau der Fall, in dem sich dieser Vorteil nicht zeigt; dieser Baseline begünstigt daher strukturell den No-Index-Standard bei der Suche. Ob dieser Vorteil mit wachsenden Daten anhält – und ob die Schreibzeit-Degradierung, nicht nur die reine Geschwindigkeit, zunehmend dominiert – ist genau das, was der nächste Beitrag messen soll.

## Nächstes in der Serie

Dies ist der Ausgangspunkt. In den nächsten Beiträgen wechseln wir vom Baseline zu schwereren Workloads – größere Datensätze und inkrementelle Last –, um zu messen, wie die Import-Geschwindigkeit mit zunehmenden Datenmengen abnimmt, wie CRUD und komplexe Suchen (Sortierung und Joins) auf einer vollen Datenbank standhalten und wie sich der Speicherunterschied bei realistischen Datenvolumina projiziert.

*Folgen Sie uns auf [LinkedIn](https://www.linkedin.com/company/health-samurai) für das nächste Benchmark-Update.*