Java-Frameworks im Container

Spring Boot oder Quarkus: was Startzeit und Speicher im Betrieb wirklich kosten

Die Zahlen aus Vergleichsmessungen stimmen meistens. Ob sie in eurer Rechnung ankommen, entscheidet nicht das Framework, sondern die Frage, wie oft eure Dienste starten und wie viele davon gleichzeitig laufen.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Seit 1997 am Markt Kleine Gruppen Präsenz und Live-Online Zertifizierte Trainer
Worum es geht

Entschieden wird nach Startzeiten, die im eigenen Betrieb niemand jemals bezahlt

Der Anlass ist fast immer derselbe. Jemand bringt eine Messung mit, in der ein Quarkus-Dienst als Native Image in wenigen Millisekunden startet und mit einem Bruchteil des Speichers auskommt, den die Spring-Boot-Fassung belegt. Die Zahlen sind in der Regel korrekt. Die Frage, die dabei übersprungen wird, lautet: Wie oft startet euer Dienst eigentlich? Bei einem Dienst, der einmal pro Auslieferung startet und danach wochenlang läuft, ist eine Verbesserung der Startzeit um zwei Sekunden ein Wert, der nirgendwo ankommt.

Die zweite Verwechslung betrifft die Zuordnung. Der große Teil des Unterschieds kommt nicht vom Framework, sondern von der Übersetzungsart. Ein Quarkus-Dienst auf der normalen JVM startet ebenfalls in Sekundenbruchteilen schneller als eine vergleichbare Spring-Boot-Anwendung, aber der spektakuläre Abstand entsteht erst mit dem Native Image. Und natives Übersetzen können beide. Wer den Vergleich fair aufziehen will, muss deshalb vier Varianten betrachten und nicht zwei.

Die dritte Stelle, an der Entscheidungen kippen, ist das Personal. Spring ist in deutschen Unternehmen die Voreinstellung, und das schlägt auf zwei Ebenen durch: Wer neu ins Team kommt, kann es mit hoher Wahrscheinlichkeit schon, und wer eine Frage hat, findet die Antwort in Minuten. Bei Quarkus ist die Dokumentation gut und die Gemeinschaft aktiv, aber der Kreis der Leute, die es im Lebenslauf stehen haben, ist deutlich kleiner. Diese Überlegung wiegt in der Praxis schwerer als jeder Benchmark, weil sie jeden Monat wirkt und nicht nur im Lasttest.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Der direkte Vergleich

Die Kriterien, an denen die Wahl tatsächlich hängt

Verglichen werden hier nicht Messreihen aus fremden Projekten, sondern die Eigenschaften, die sich in eurem Betrieb und in eurem Team bemerkbar machen: Startverhalten, Speicher, Aufwand für das Native Image, Rückmeldezeit beim Entwickeln, Umfang des Ökosystems und die Frage, wie lange eine gewählte Version trägt.

Spring Boot

die verbreitete Voreinstellung für Java-Dienste, seit Version 4.0 auf Spring Framework 7 und Jakarta EE 11, mit eigener Ahead-of-Time-Verarbeitung für Native Images

Quarkus

auf Container zugeschnittenes Framework, das einen großen Teil der Arbeit in die Bauzeit verlegt, mit LTS-Reihen alle sechs Monate und enger Anbindung an die native Übersetzung

Wie schnell ist der Dienst nach dem Start ansprechbar?

Spring Boot

Auf der JVM liegt der Start bei einer typischen Anwendung im Sekundenbereich, weil ein Teil der Konfiguration erst beim Hochfahren entschieden wird. Mit der Ahead-of-Time-Verarbeitung und dem AOT-Zwischenspeicher lässt sich das deutlich drücken, und als Native Image fällt es in den Millisekundenbereich.

Quarkus

Ein großer Teil der Arbeit passiert bereits beim Bauen, deshalb ist auch die JVM-Fassung spürbar schneller ansprechbar. Als Native Image startet ein Dienst in wenigen Millisekunden, und genau darauf ist das Framework von Anfang an zugeschnitten.

Wie viel Arbeitsspeicher belegt ein Dienst im Dauerbetrieb?

Spring Boot

Auf der JVM kommt zum eigentlichen Bedarf der Anwendung das hinzu, was Laufzeitumgebung, Metaspace und der vorgehaltene Heap belegen. Für die meisten Dienste ist das unerheblich, bei vielen kleinen Instanzen summiert es sich sichtbar.

Quarkus

Weil weniger zur Laufzeit entschieden wird, bleibt der belegte Speicher näher an dem, was die Anwendung selbst braucht. Als Native Image entfällt die Laufzeitumgebung ganz, und der Abstand wird deutlich.

Wie aufwendig ist der Weg zu einem Native Image?

Spring Boot

Der Weg ist eingebaut und dokumentiert, verlangt aber eine geschlossene Weltannahme: Der Klassenpfad steht zur Bauzeit fest, Beans dürfen sich zur Laufzeit nicht mehr ändern, und Profile sowie bedingte Konfiguration über Eigenschaften sind eingeschränkt. Für Anwendungen, die stark von diesen Mitteln Gebrauch machen, ist das ein echter Umbau.

Quarkus

Die native Übersetzung ist der vorgesehene Fall und nicht die Ausnahme. Die Erweiterungen bringen die nötigen Hinweise für Reflection, Ressourcen und Proxies gleich mit, und mit Mandrel steht eine Distribution bereit, die genau auf diesen Zweck ausgerichtet ist.

Wie schnell siehst du beim Entwickeln eine Änderung?

Spring Boot

Die Entwicklerwerkzeuge starten die Anwendung bei einer Änderung neu, was je nach Größe einige Sekunden dauert. Für Datenbanken und Nachbardienste richtet ihr euch die Testumgebung selbst ein, üblicherweise über Testcontainers.

Quarkus

Der Entwicklungsmodus lädt Änderungen bei der nächsten Anfrage nach, ohne dass jemand neu startet. Dazu kommen die Development Services, die Datenbank, Nachrichtendienst oder Identitätsanbieter beim Start automatisch als Container hochziehen.

Wie groß ist der Vorrat an fertigen Bausteinen und an Wissen im Markt?

Spring Boot

Für nahezu jede Aufgabe gibt es einen offiziellen Baustein, dazu eine sehr große Menge an Beispielen, Fragen und Antworten. Wer neu ins Team kommt, kennt es mit hoher Wahrscheinlichkeit bereits, und eine Nachbesetzung ist entsprechend einfacher.

Quarkus

Die Erweiterungen decken den üblichen Bedarf ab und die Dokumentation ist gut gepflegt. Bei Randfällen und bei Anbindungen an Werkzeuge einzelner Hersteller greift man aber öfter zu einer allgemeinen Bibliothek, und der Kreis der Leute mit Erfahrung ist kleiner.

Wie lange trägt eine einmal gewählte Version, ohne dass jemand nachziehen muss?

Spring Boot

Jede Nebenversion bekommt freie Unterstützung für etwa ein Jahr, danach gibt es kommerzielle Verlängerungen, die für einzelne Reihen sehr weit reichen. Der Zeitplan ist veröffentlicht, und die Aktualisierung innerhalb einer Hauptversion ist meist unspektakulär.

Quarkus

Alle sechs Monate erscheint eine LTS-Reihe, die zwölf Monate lang Fehlerbehebungen und Sicherheitsaktualisierungen bekommt. Wer nicht auf einer LTS-Reihe bleibt, folgt einem Rhythmus von vier bis sechs Wochen. Für längere Fenster gibt es kommerzielle Builds von Red Hat und IBM.

Was passt wann

Wenn eure Dienste dauerhaft laufen, selten neu starten und mit fester Instanzzahl betrieben werden
bleib bei Spring Boot und steck die gesparte Zeit in Tests und in die Betriebsfähigkeit.
Wenn Dienste auf null skalieren, als kurzlebige Aufgaben laufen oder in dreistelliger Instanzzahl stehen
rechnet Quarkus mit Native Image durch, hier ist der Unterschied groß genug, um in der Rechnung anzukommen.
Wenn nur die Startzeit stört und das Team Spring bereits sicher beherrscht
prüf zuerst die Ahead-of-Time-Verarbeitung, den AOT-Zwischenspeicher und das Native Image in Spring Boot selbst, bevor ihr das Framework wechselt.
Wenn ihr eine ganze Plattform aus vielen Diensten baut und niemand im Haus Quarkus kennt
fang mit einem einzelnen, klar abgegrenzten Dienst an und entscheide erst nach einem halben Jahr Betrieb über den Rest.

Fünf Fragen, und das Framework steht fest

  1. 01 Wie oft startet der Dienst pro Woche? Selten heißt: Startzeit ist kein Kriterium.
  2. 02 Wie viele Instanzen laufen dauerhaft? Erst dreistellig zählt der Speicher in der Rechnung.
  3. 03 Muss die erste Anfrage nach dem Start innerhalb einer zugesagten Zeit beantwortet sein?
  4. 04 Wie viele Bibliotheken brauchen eigene Hinweise für die statische Analyse?
  5. 05 Wie viele Leute im Haus können das Framework heute schon?
Was du mitnimmst

Die Rechnung, die vor der Entscheidung stehen sollte

Sechs Zahlen entscheiden die Frage, und alle sechs liegen entweder schon vor oder lassen sich an einem Tag erheben. Erst wenn sie auf dem Tisch liegen, lohnt sich eine Diskussion über Frameworks.

Wie oft startet ein Dienst wirklich

Zähl die Starts pro Woche über alle Instanzen. Bei einem Dienst mit fester Instanzzahl und wöchentlicher Auslieferung sind das wenige Dutzend, und die Startzeit ist damit als Kriterium erledigt. Bei einer Plattform, die auf null skaliert oder Aufgaben als kurzlebige Container ausführt, sind es Tausende, und dann ist die Startzeit die zentrale Größe.

Wie viele Instanzen dauerhaft laufen

Der Speichervorteil wird erst in der Summe sichtbar. Bei fünf Instanzen ist ein Unterschied von ein paar hundert Megabyte Rauschen im Cluster. Bei dreistelliger Instanzzahl ist es eine Zeile im Budget, die sich vorher ausrechnen lässt. Rechne mit euren tatsächlichen Grenzwerten aus der Container-Konfiguration, nicht mit dem, was der Prozess im Leerlauf anzeigt.

Ob die Kaltstartzeit an einer Zusage hängt

Wenn eine erste Anfrage nach dem Hochfahren innerhalb einer zugesagten Zeit beantwortet sein muss, ist das ein anderes Kriterium als der Speicherverbrauch. Bei Funktionen, die vom Ereignis geweckt werden, entscheidet es über die Machbarkeit. Bei einem Dienst hinter einem Lastverteiler, der langsam hochfährt, entscheidet es über nichts.

Was das Native Image an Bauzeit kostet

Ein Native Image braucht deutlich länger im Bau als ein gewöhnliches Java-Artefakt, und diese Zeit fällt bei jedem Durchlauf an. Rechne den CI-Server mit ein, nicht nur die Laufzeit. Eine übliche Aufteilung ist, im Alltag auf der JVM zu bauen und das Native Image nur für die Auslieferung zu erzeugen.

Welche Bibliotheken ihr mitbringt

Für ein Native Image muss die statische Analyse alles kennen, was zur Laufzeit über Reflection, Ressourcen, Serialisierung oder dynamische Proxies angesprochen wird. Frameworks liefern diese Hinweise für ihre eigenen Bausteine mit. Für eure Sonderfälle und für weniger verbreitete Bibliotheken schreibt ihr sie selbst. Zähl diese Bibliotheken, bevor du einen Termin zusagst.

Wer den Dienst in drei Jahren pflegt

Das ist keine technische Zahl, aber die mit der längsten Wirkung. Frag, wie viele Leute im Haus das Framework heute können, wie oft im Team gewechselt wird und wie realistisch eine Nachbesetzung ist. Bei einem einzelnen Dienst darf die Antwort ein Experiment sein. Bei einer Plattform aus dreißig Diensten ist sie die eigentliche Entscheidung.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt

Woher die Startzeit tatsächlich kommt

Eine klassische Java-Anwendung entscheidet einen erheblichen Teil ihrer Konfiguration beim Hochfahren. Der Klassenpfad wird durchsucht, Annotationen werden gelesen, Bedingungen werden ausgewertet, Proxies werden erzeugt. Bei Spring Boot heißt dieses Verfahren automatische Konfiguration, und es ist der Grund dafür, dass eine Anwendung mit wenigen Zeilen Konfiguration lauffähig ist. Es ist zugleich der Grund dafür, dass der Start Zeit braucht, und diese Zeit wächst mit der Anzahl der Bausteine.

Quarkus verlegt genau diese Arbeit in die Bauzeit. Was sich beim Bauen entscheiden lässt, wird beim Bauen entschieden, und das Ergebnis landet als erzeugter Code im Artefakt. Deshalb ist auch die Fassung auf der gewöhnlichen JVM schon schneller ansprechbar, ohne dass jemand nativ übersetzt hat. Der Preis dafür ist eine geringere Beweglichkeit zur Laufzeit: Was zur Bauzeit feststeht, kann später nicht mehr über eine Eigenschaft umgeschaltet werden.

Spring geht denselben Weg inzwischen ebenfalls, nur unter anderem Namen. Die Ahead-of-Time-Verarbeitung erzeugt beim Bauen Java-Quellcode und Bytecode für das, was sonst zur Laufzeit über Reflection passiert wäre, dazu die Hinweisdateien für GraalVM. Dazu kommt der AOT-Zwischenspeicher, der den Start auf der JVM beschleunigt, ohne dass ein Native Image nötig wäre. Wer nur an der Startzeit arbeiten will, sollte diese beiden Wege ausprobieren, bevor die Frage nach dem Framework überhaupt gestellt wird.

Was ein Native Image wirklich kostet

Ein Native Image ist ein vollständiges, plattformspezifisches Programm ohne Java Virtual Machine daneben. Damit das funktioniert, analysiert der Übersetzer die Anwendung vom Einstiegspunkt aus statisch. Code, der dabei nicht erreichbar ist, fliegt heraus. Das ist der Grund für den geringen Speicherbedarf und zugleich die Ursache aller Schwierigkeiten: Alles, was zur Laufzeit dynamisch angesprochen wird, ist für die Analyse unsichtbar und muss ihr ausdrücklich mitgeteilt werden. Das betrifft Reflection, Ressourcen im Klassenpfad, Serialisierung, dynamische Proxies und Aufrufe über JNI.

Dazu kommen weitere Festlegungen, die Anwendungen betreffen können, ohne dass es jemand erwartet hat. Der Klassenpfad steht zur Bauzeit fest und lässt sich nicht mehr ändern. Es gibt kein verzögertes Laden von Klassen, alles Ausgelieferte liegt beim Start im Speicher. Bei Spring kommt die geschlossene Weltannahme hinzu: Die Beans der Anwendung dürfen sich zur Laufzeit nicht mehr unterscheiden, Profile sind eingeschränkt, und Eigenschaften, die darüber entscheiden, ob eine Bean überhaupt entsteht, funktionieren nicht mehr. Eine Anwendung, die stark mit bedingter Konfiguration arbeitet, braucht dafür einen Umbau.

Auf der Werkzeugseite ist noch eine Änderung zu beachten. GraalVM für JDK 24 war die letzte Fassung, die Oracle als Teil der Java-SE-Produkte lizenziert und unterstützt hat. Für Quarkus ist das weniger relevant, weil dort Mandrel die übliche Wahl ist, eine Verteilung, die genau auf die native Übersetzung von Quarkus-Anwendungen zugeschnitten ist. Wer sein Native Image über eine Oracle-Vertragsbeziehung absichern wollte, sollte den Punkt aber im Beschaffungsprozess prüfen, bevor der erste Dienst produktiv geht.

Das Ökosystem ist der Preis, den man zuletzt merkt

Die Frage, ob es für eine Aufgabe einen fertigen Baustein gibt, entscheidet über deutlich mehr Kalenderzeit als jede Startzeit. Bei Spring gibt es für nahezu jede verbreitete Anforderung ein offizielles Projekt: Datenzugriff, Sicherheit, Nachrichten, Batch-Verarbeitung, Integration, Beobachtbarkeit. Bei Quarkus ist die Abdeckung für den üblichen Bedarf ebenfalls gut, in der Breite fehlt aber mehr. Bei einem Werkzeug eines einzelnen Herstellers greift man dort öfter zu einer allgemeinen Bibliothek oder schreibt direkt gegen die HTTP-Schnittstelle.

Quarkus bietet für den Einstieg eine Brücke an: Es gibt Erweiterungen, die einen Teil der Spring-Programmierschnittstellen nachbilden, damit ein Team mit vertrauten Annotationen anfangen kann. Diese Brücke ist als Einstiegshilfe gedacht und nicht als vollständiger Ersatz. Wer eine große Spring-Anwendung Zeile für Zeile darüber portieren will, arbeitet gegen die Absicht des Werkzeugs und landet in Randfällen, für die es keine Antwort gibt. Die tragfähige Variante ist, einen neuen Dienst in Quarkus zu schreiben und die bestehenden zu lassen, wo sie sind.

Der zweite Teil des Preises ist personell. Wenn im Haus dreißig Leute Spring können und zwei Quarkus, dann ist jede Quarkus-Anwendung ein Engpass in der Urlaubsplanung, in der Rufbereitschaft und bei der Nachbesetzung. Das ist kein Argument gegen Quarkus, aber es ist ein Posten, der in die Rechnung gehört, und zwar auf derselben Seite wie die eingesparten Cloud-Kosten. Eine Schulung für das Team ist an dieser Stelle die günstigere Antwort als ein Dienst, den nur eine Person versteht.

Beide nebeneinander betreiben, und wie das gut geht

Der Normalfall in Häusern mit vielen Diensten ist nicht die Entscheidung für eines von beiden, sondern das Nebeneinander. Dienste reden über HTTP oder über einen Nachrichtendienst miteinander, und dahinter ist das Framework egal. Was das kostet, sind zwei Werkzeugketten, zwei Sätze Basisabbilder, zwei Bauprozesse und zwei Sätze von Konventionen für Konfiguration, Protokollierung und Messwerte. Das sollte eine bewusste Entscheidung sein und nicht das Ergebnis einer persönlichen Vorliebe in einem einzelnen Team.

Wenn ihr euch für das Nebeneinander entscheidet, lohnt sich eine klare Regel dafür, welcher Dienst wohin gehört. Eine tragfähige Formulierung ist: Alles, was dauerhaft läuft und viel Fachlichkeit enthält, bleibt bei Spring Boot. Alles, was auf Ereignisse reagiert, häufig startet oder in sehr vielen Instanzen läuft, ist ein Kandidat für Quarkus mit Native Image. Diese Regel lässt sich in einem Satz erklären, und genau das ist ihre Qualität: Sie überlebt den Wechsel der Personen, die sie aufgeschrieben haben.

Was in beiden Welten gleich bleiben sollte, sind die Betriebsschnittstellen. Health-Checks, Metriken, Tracing und die Struktur der Protokollausgabe gehören vereinheitlicht, sonst hat der Betrieb zwei Anwendungsklassen mit zwei Vorgehensweisen. Beide Frameworks unterstützen die verbreiteten Formate dafür, es ist also keine technische, sondern eine organisatorische Aufgabe, und sie sollte erledigt sein, bevor der zweite Dienst in der neuen Welt entsteht.

Dazu passende Kurse

Wenn bei dieser Abwägung im Team unterschiedliche Vorstellungen davon aufeinandertreffen, was ein Framework überhaupt leisten muss, sind Java-Kurse für Teams, die Dienste in Containern betreiben der schnellste Weg zu einer gemeinsamen Grundlage.

Fällt die Entscheidung zugunsten kurzlebiger Dienste, findest du bei cmt Trainings rund um den Betrieb von Diensten in der Cloud .

Wissen prüfen

Wie sicher bist du beim Thema wirklich?

Lesen fühlt sich schnell nach Können an. Ein kurzer Test zeigt dir, was davon schon sitzt und wo sich ein Kurs lohnt. Kostenlos, ohne Anmeldung, mit einer Erklärung zu jeder Antwort.

Sehr umfangreicher Überblick über Zusammenhänge und Anwendungsbereiche. Sehr zu empfehlen.
Einführung in die Programmierung für Programmiereinsteiger
Effektives, gemeinsames Erarbeiten der Aufgaben mit vielen praktischen Tipps.
Groovy Grundkurs
Sehr guter Trainer und gute Aufbereitung der Inhalte und auch eingehen auf Fragen der Beteiligten.
Unreal Engine Kurs für Einsteiger

Häufige Fragen

Ist Quarkus wirklich schneller als Spring Boot?
Beim Starten ja, und zwar deutlich, weil ein großer Teil der Arbeit in die Bauzeit verlegt wird. Beim Durchsatz einer laufenden Anwendung verschwindet der Unterschied hinter Datenbank- und Netzzeit. Verlässlich sichtbar bleibt der Abstand an zwei Stellen: bei der Zeit bis zur ersten beantworteten Anfrage nach dem Hochfahren und beim belegten Speicher pro Instanz.
Können wir eine bestehende Spring-Boot-Anwendung nach Quarkus portieren?
Technisch gibt es Erweiterungen, die einen Teil der Spring-Schnittstellen nachbilden, und für kleine Dienste kann das funktionieren. Bei einer gewachsenen Anwendung ist der Weg selten wirtschaftlich, weil die Randfälle nicht abgedeckt sind und ihr am Ende zwei Denkweisen im selben Code habt. Der übliche Weg ist, neue Dienste in Quarkus zu schreiben und die bestehenden dort zu lassen, wo sie sind.
Brauchen wir für den Vorteil zwingend ein Native Image?
Nein, aber der große Teil des Abstands hängt daran. Auf der gewöhnlichen JVM ist Quarkus ebenfalls schneller ansprechbar und sparsamer, der Unterschied liegt dann aber in einer Größenordnung, die sich nur bei sehr vielen Instanzen bemerkbar macht. Wenn ihr das Native Image aus guten Gründen ausschließt, sollte die Entscheidung nach anderen Kriterien fallen.
Was ist mit den Einschränkungen von Native Image bei Spring?
Sie sind dokumentiert und betreffen vor allem die geschlossene Weltannahme: Die Beans stehen zur Bauzeit fest, Profile sind eingeschränkt, und Eigenschaften, die über die Existenz einer Bean entscheiden, greifen nicht mehr. Für eine Anwendung, die stark mit bedingter Konfiguration arbeitet, ist das ein echter Umbau. Für eine Anwendung mit klarer, statischer Struktur ist es meist eine Formalität.
Wie oft müssen wir bei Quarkus die Version wechseln?
Wer auf einer LTS-Reihe bleibt, hat zwölf Monate Ruhe, und alle sechs Monate erscheint die nächste. Wer der normalen Reihe folgt, sieht alle vier bis sechs Wochen eine neue Nebenversion. Für Häuser mit festen Wartungsfenstern ist die LTS-Reihe die richtige Wahl, und für längere Fenster gibt es kommerzielle Builds von Red Hat und IBM.
Persönlich für dich da

Deine Ansprechpartner

Du bist dir nicht sicher, welcher Kurs oder welches Level zu dir passt? Wir beraten dich persönlich und kostenlos.

Yves Hoppe

Yves Hoppe

Weiterbildung & Beratung

Hilft dir, aus dem Programmierung-Programm den passenden Kurs für deinen Stand zu finden.

Norbert Jansen

Norbert Jansen

Beratung & Inhouse

Plant mit dir Inhouse-Trainings, die auf eure Abläufe und euren Datenbestand zugeschnitten sind.

Beide Frameworks am selben Dienst gegeneinander stellen

Bei cmt baust du im Quarkus-Kurs einen Dienst von Grund auf und übersetzt ihn nativ. Danach kennst du die Stellen, an denen das Framework Arbeit abnimmt, und die, an denen es Vorgaben macht.