KfW-Förderprogamm 442 – technische Betrachtung

Disclaimer: Dieser Post spiegelt meine private Erfahrung mit dem Antragssystem wider und steht in keinem Bezug zu meiner beruflichen Tätigkeit. Meine einzige Verbindung zum Portal „Meine KfW“ ist mein privater Account auf der Plattform, den ich zur Antragstellung angelegt habe. Sämtliche Inhalte dieses Posts basieren auf Informationen, die allen Antragsteller:innen zugänglich waren.

Hintergrund

In den vergangenen Tagen haben bereits viele Medien über die Antragsphase des KfW-Förderprogramms 442 „Solarstrom für Elektroautos“ berichtet (etwa heise.de, tagesschau.de). Dieser Post wird die grundsätzlichen Probleme daher nicht erneut darstellen, sondern stattdessen einige Details hinzufügen, die in der breiten Berichterstattung bisher nicht vorkamen – sicher auch, weil sie vor allem für Web-Entwickler und -Tester interessant sein dürften, nicht aber für den Großteil der Bürger. Dennoch haben sich einige „Puzzleteile“ so perfekt aneinander gefügt, dass die hier aufgestellten Hypothesen zu den Gründen für den holprigen Verlauf der Antragsphase zunehmend wahrscheinlich erscheinen.

Die Beantragung

Bei Ankündigung des Förderprogramms war zunächst nur bekannt, dass es „am 26.09.“ starten würde. Dies wurde kurz vorher dann zu „im Laufe des Vormittags“ präzisiert, was vielen Interessierten eine schlaflose Nacht erspart haben dürfte. Pünktlich um 8 Uhr wurde die Informationsseite zum Programm sowie der im Merkblatt verwendete Shortlink (http://www.kfw.de/442-MeineKfW) angepasst, und das Programm 442 auf der Startseite des Portals „Meine KfW“ live geschaltet. Dieses stand quasi sofort unter enormer Last und quittierte jeden Seitenaufruf mit langen Ladezeiten und gelegentlichen Fehlerseiten (HTTP 504 Gateway Timeout). Nach diversen Versuchen erschien schließlich die Startseite zur Antragstellung mit dem Hinweis, man müsse zunächst einen Account erstellen. Dieser Prozess lief auf einem separaten Authentifizierungssystem ab, welches erstaunlich responsiv war, so dass die Account-Erstellung schnell abgeschlossen werden konnte, inklusive der Bestätigung der E-Mail-Adresse über den üblichen Bestätigungslink per Mail. Kaum war der Login erledigt, folgen wieder eine Reihe von sehr langsamen Requests, bis schließlich eine Web App angezeigt wurde, die sich erstaunlich flüssig bedienen ließ. Hier wurde offensichtlich auf eine Single-Page App gesetzt, die die Bürger:in sehr angenehm durch eine Reihe von Fragen führte: Adresse, Bestätigung der Fördervoraussetzungen, Angaben zur Größe der geplanten Anlage etc. – in kürzester Zeit waren die Schritte 1-4 erledigt.

Der Flaschenhals

Am Ende von Schritt 4 erschien zur Bestätigung eine Übersicht, in der die aufgrund der zuvor gemachten Angaben zu erwartende Fördersumme angezeigt werden sollte. Hier erschien ein Lade-Symbol, der Browser machte erstmals wieder einen Server-Request und wartete auf Antwort. Lange, aber nicht so lange wie bei den ersten Seitenaufrufen im Portal. Dann erschien eine Fehlermeldung, die etwa „Hoppla, da ist etwas schiefgegangen. Versuchen Sie bitte, den letzten Schritt erneut durchzuführen.“ lautete. Doch dies führte zum exakt selben Fehler. Immer und immer wieder.

In der Hoffnung etwas über die Fehlerursache herauszufinden, öffnete ich die Browser-Dev-Tools und wechselte auf den Netzwerk-Tab: Zum Abruf der zu erwartenden Fördersumme wurde ein Request an die URL /calcGrantAmount gesendet, welcher reproduzierbar fehlschlug, und zwar immer nach exakt 10 Sekunden. Vorige Seitenaufrufe hatten sich langsamer angefühlt. An dieser Stelle regte sich der Verdacht, dass der Abbruch clientseitig passierte, und der Server einfach permanent länger als 10 Sekunden für die Antwort benötigte. Dieser Verdacht erhärtete sich, als ich im JavaScript-Debugger einen XHR-Breakpoint für die URL calcGrantAmount setzte und das Request-Objekt inspizierte: Es enthielt einen Parameter timeout: 1e5 (wobei 1e5 die Kurzschreibweise für 1 * 10 ^ 5 ist, also für 10.000 Millisekunden steht).

Da die Server deutlich langsamer antworteten als erwartet, vermutete ich, dass viele meiner vorigen Requests für den Förderbetrag tatsächlich beantwortet worden wären, hätte der Browser nur lange genug auf die Antwort gewartet. So allerdings standen gerade tausende Menschen am Ende von Schritt 4 und setzten alle 12-15 Sekunden (10 Sekunden warten, Fehlermeldung bestätigen, ein Schritt zurück, ein Schritt vor) weitere Requests ab, die ihrerseits 20 und mehr Sekunden benötigten. Parallel dazu kamen sicher im Laufe der Zeit weitere Antragsteller:innen nach, die aber alle in Schritt 4 „gefangen“ waren und das Problem weiter und weiter verstärkten.

Ein Lösungsansatz

Wenn man nur diesen Timeout-Wert im Browser von 10 Sekunden auf deutlich mehr erhöhen, und der dann einfach geduldig auf die Antwort warten könnte… An dieser Stelle fiel mir die Debugger-Option auf, bei Erreichen eines Breakpoints Aktionen auszuführen. Einer der Aktionstypen lautete „JavaScript auswerten“, eine weitere Option „Nach Auswertung automatisch fortsetzen“. Das klang vielversprechend – in welchem Feld der Timeout festgelegt war, wusste ich ja bereits. (Hinweis: Letztlich standen an zwei Stellen Timeouts, die anscheinend beide eine Bedeutung hatten)

Könnte man damit vermeiden, dass der Browser aufgibt auf eine Server-Antwort zu warten?

Erste Erfolge

Ein Klick auf „OK“, ein Schritt zurück, ein Schritt vor, und auf die Anzeige des Förderbetrags warten. 10 Sekunden… Keine Fehlermeldung… 15 Sekunden… 20 Sekunden… Nach 23 Sekunden erscheint ein Betrag, und der „Weiter“-Button wird freigeschaltet.

Dann in Schritt 5 und 6 noch ein paar Angaben zur Person und eine abschließende Zusammenfassung aller zuvor getätigten Eingaben – und ein großer „Senden“-Button. Klick… und nach 10 Sekunden die Meldung „Hoppla… (usw.)“. Also die o.g. Anpassung auch für die URL /saveRequest durchführen.

Ein Klick auf „OK“, ein Schritt zurück, ein Schritt vor, „Senden“ und warten. 10 Sekunden… Keine Fehlermeldung… 15 Sekunden… 20 Sekunden… und irgendwann eine Bestätigungsseite:

Erstaunlich. Allem Anschein nach funktionierte das System eigentlich korrekt, aber niemand merkte es, weil die Browser reihenweise vorher aufhörten „zuzuhören“ und den Berg an Anfragen immer weiter anwachsen ließen.

Im Laufe der folgenden Stunden hörte ich ähnliche Erlebnisse aus dem Bekanntenkreis: Entweder war der Zugriff auf das Portal komplett unmöglich, man drehte sich aufgrund verwirrender Benutzerführung im Kreis, oder man steckte bei Schritt 4 fest und war dort in einer Endlosschleife aus Fehlermeldungen gefangen.

Ein Verdacht

Die beiden oben genannten Requests calcGrantAmount und saveRequest unterschieden sich in einem fundamentalen Punkt: Der erste, calcGrantAmount in Schritt 4, war vermutlich „stateless“, d.h. er berechnet basierend auf den Eingaben die voraussichtliche Höhe der Förderung und gibt diese in der Antwort zurück. Wenn beim Abschicken also nach 10 Sekunden der Browser eine Fehlermeldung zeigt, der Server die Anfrage aber pflichtschuldig weiter bearbeitet und nach 20+ Sekunden beantwortet, dann türmen sich zwar Anfragen auf, die das System weiter belasten, aber ansonsten sollte das keine Seiteneffekte haben.

Der zweite Request führte jedoch dazu, dass der Antrag eine „Zuschussreferenz“-Nummer bekommt, also vermutlich in der Datenbank gespeichert und als erfolgreich eingereichter Antrag gekennzeichnet wird. Wenn nun also Nutzer in diesem Schritt nach 10 Sekunden eine Fehlermeldung bekommen, der Server die Anfrage aber im Hintergrund weiter bearbeitet… Dann müsste das dazu führen, dass unzählige Anträge mehrfach, vermutlich dutzende Male, angenommen werden und in der Datenbank landen, ohne dass die Nutzer davon etwas mitbekommen. Denn zu diesem Zeitpunkt sahen sie ja bereits eine Fehlermeldung und versuchten daher verzweifelt weiter, den Antrag einzureichen.

Der Antrag eines Bekannten wurde nach unzähligen Versuchen seinerseits gegen 13:30 Uhr mit einer Erfolgsseite bedacht und erhielt eine Zuschussreferenznummer jenseits der 56.000.

Unsicherheit und Datenchaos

Während mein eigener Antrag von ca. 10 Uhr bereits kurz darauf mit einer E-Mail bestätigt wurde und im Portal „Meine KfW“ als eingegangen zu sehen war (wie es vermutlich für alle Anträge angedacht war), war bei Anträgen aus dem Bekanntenkreis von 10:20 Uhr und 13:30 Uhr keine dieser Bestätigungen zu sehen. Keine E-Mail, keine Darstellung im Portal – lediglich Screenshots bzw. Ausdrucke der Erfolgsseite mit Zuschussreferenznummer (s.o.) dienten als Bestätigung, dass anscheinend alles funktioniert hatte. Die Unsicherheit blieb, da die Anträge nirgends mehr zu sehen waren.

Eventuell waren der KfW zu diesem Zeitpunkt bereits die Probleme mit doppelt eingegangenen Anträgen bekannt, und man wollte niemanden mit mehrfachen Mails verwirren – oder die Mehrfacheinreichungen führten dazu, dass das bereitstehende Budget bereits als ausgeschöpft erschien, sodass bewusst keine automatischen Bestätigungen mehr versendet wurden?

Der Bekannte mit Antrag Nr. 56.000+ machte sich jedenfalls keine Hoffnungen mehr, dass sein Antrag (gegeben das Budget vom 300 Mio € und einer Fördersumme pro Antrag von 4.850 – 10.200 € pro Antrag) noch eine Zusage erhalten würde – selbst wenn er irgendwann noch im Portal als eingereicht aufgeführt werden sollte.

In jedem Fall keimte bei mir der Verdacht, dass in den folgenden Tagen deutlich mehr manuelle Nacharbeiten an den Datensätzen erforderlich sein würden, als es beim Entwurf des Systems vorgesehen war.

Aufräumarbeiten

Wiederum aus dem Bekanntenkreis erfuhr ich, dass über die öffentlich bekannte Telefonnummer der KfW bereits am Mittwochmittag keine Auskunft zur aktuellen Situation des eigenen Antrags zu erhalten war. Die offizielle Erklärung lautete „technische Probleme“, verbunden mit dem Rat, doch am Freitag noch einmal im Portal zu schauen, da bis dahin vermutlich die Anträge korrekt angezeigt würden.

Nach 16 Uhr am Mittwoch erhielt ich eine Mail der KfW mit folgendem Zusatz:

Wichtiger Hinweis:

Die elektronischen Schreiben werden sukzessive generiert und sollten, sofern noch nicht erfolgt, in Kürze bei Ihnen eingehen. Anschließend wird Ihnen Ihr erfolgreicher Zuschussantrag auch im Kundenportal „Meine KfW“ angezeigt.

Ihnen wird aktuell noch mehr als ein eingereichter Zuschussantrag angezeigt? Gut für Sie: Es ist für Sie nichts weiter zu tun. Für Sie ist genau ein Zuschuss reserviert. Mehrfachanträge für identische Vorhaben werden in Kürze korrigiert und im Kundenportal als storniert angezeigt, sodass Ihnen für die weiteren Schritte der tatsächlich gestellte Zuschussantrag als aktiv angezeigt wird. Alle bisher erhaltenen Mails zu den vermeintlichen weiteren Anträgen können Sie ignorieren.  Hierfür wurden keine Mittel reserviert. Wir bitten um Entschuldigung für die aus dem Anzeigefehler resultierende Verwirrung.

Quelle: Mail der KfW an Antragsteller:innen

Ich sehe das als Bestätigung meiner Vermutung, dass saveRequest tatsächlich Anträge mehrfach angenommen und persistiert hat.

Unterdessen meldeten sich Bekannte, die nun auch Förderzusagen per Mail bekommen hatten, deren Anträge aber im Portal immer noch nicht sichtbar waren – darunter der oben genannte mit Antragsnummer weit jenseits der 50.000. Wollte man an dieser Stelle Mutmaßungen über die Art der Aufräumarbeiten anstellen, könnte man auf die Idee kommen, dass die Datensätze aus dem System exportiert und außerhalb des Systems von Hand mit Office-Software auf Duplikate geprüft und bereinigt worden sind, um wenigstens möglichst schnell die Antragsteller:innen zu informieren. Gegeben die große Unsicherheit und den Zeitdruck mag das in diesem Moment sogar vielleicht die effektivste Variante gewesen sein.

Ein Blick in die Zukunft

Für die bereits in Aussicht gestellte zweite Ausgabe des Förderprogramms im nächsten Jahr sollten Lasttestfälle mit deutlich längeren als den üblichen Server-Antwortzeiten definiert, und insbesondere die Default-Timeouts der verwendeten JavaScript-Bibliothek im Auge behalten werden. Dann sollte die Last am Tag der Antragstellung – und vielleicht wichtiger: der manuelle Aufwand im Anschluss – deutlich geringer ausfallen. Und, um mit einer positiven Note zu enden, der moderne, einfach gehaltene und angenehm zu benutzende Workflow deutlich besser zur Geltung kommen.

Ohne diesen (zugegeben schwer vorherzusehenden) Effekt der Request-Verstärkung und den daraus resultierenden Performance-Einbruch sowie das Daten-Chaos im Anschluss wäre das nämlich meiner Meinung nach ein durchaus ansehnliches Beispiel für Digitalisierung in der Verwaltung gewesen.

4 Kommentare zu „KfW-Förderprogamm 442 – technische Betrachtung

  1. Hi Andreas

    Der Podcast „Die Lage der Nation“ hat mich hierher geführt. Vielen Dank für deine ausführliche Analyse. Ich kann nur zustimmen.

    Ich möchte dem aber einen relevanten Punkt hinzufügen: Du hast völlig Recht mit dem unflexiblen Timeout des Frontends. Allerdings ist die Wurzel des Problems die Datenbankperformance.

    In meinem Fall hat das Backend 17 Sekunden benötigt, um den Antrag zu bearbeiten. Etwa 150 tausend Anträge sind an besagtem Dienstag eingegangen, in einem Zeitraum von 24 Stunden. Für eine Datenbank ist das nicht viel! Statt 17 Sekunden sollte es eher im Bereich einer Zehntelsekunde liegen, um einen neuen Datensatz anzulegen.

    Warum ist die KfW Datenbank also so langsam? Nun, für die ersten 7000 Antragsteller war das Backend noch schnell genug, also schneller als der 10 Sekunden Timeout vom Frontend. Gute Beobachter, die lange wach waren, wissen auch, dass um halb eins Nachts plötzlich alle Performanceprobleme verschwunden waren.

    Dieses Verhalten kenne ich von neuen, leeren Datenbanken. In den Worten eines Leien und aller Kürze: Für die gute Performance von Datenbanken wird ein Index der vorhandenen Daten erstellt. Dieser Index existiert bei einer leeren Datenbank aber noch nicht. Das ist eine art Henne/Ei Problem.

    Sobald Daten eingefüllt werden, wird die DB ohne brauchbaren Index also mit jedem Datensatz drastisch langsamer. Bis zu dem Zeitpunkt, an dem der Index neu berechnet wird. Wann das passiert lässt sich einstellen, im Standard ist es oftmals um Mitternacht, denn da hat das System Zeit und Ressourcen übrig.

    Abhilfen gegen dieses systematische Problem gibt es:
    1. Nachdem die ersten paartausend Datensätze hinzugefügt wurden, löst ein Datenbankadministrator manuell eine Indexerstellung aus. Oder eine vorab programmierte Automatisierung.
    2. Die Datenbank wird bereits im Vorfeld „aufgewärmt“ (en: Priming), also mit Dummy-Daten befüllt, die nur der erfolgreichen Vorab-Erstellung der Datenbankindizes dienen. Im Betrieb ignoriert die Applikation diese Daten.

    Wäre das so gemacht worden, hätten die Antragsteller und die KfW jetzt sicher weniger graue Haare.

    Lange Rede, kurzer Sinn: Die IT-Dienstleister unserer Behörden sollten einen erfahrenen Datenbankadministrator an der Entwicklung ihrer Software teilhaben lassen. Das sind Grundlagen, die regelmässig falsch gemacht werden.

    Schöne Grüße
    Raphael

    1. Vielen Dank für diese Zusatzinformationen, Raphael!
      Datenbanken sind nicht mein Spezialgebiet, daher habe ich in diese Richtung keine Vermutungen angestellt.
      Ich frage mich allerdings, warum auch die Berechnung des Förderbetrags schon dieselben Timeout-Probleme hatte wie das spätere Absenden. Die Berechnungsformel war doch simpel genug, um komplett ohne Datenbankzugriffe auszukommen.
      Übrigens ist meine Antragsnummer deutlich unter 7.000, und ich bin trotzdem in besagte Probleme gelaufen, dass die Requests schon jenseits der 20 Sekunden brauchten.

      1. Ich nehme an, die Berechnung wurde eben auch mit irgendeinem Zugriff auf die Datenbank gemacht. Sei es lesend oder schreibend. Warum auch immer.

        Natürlich sind das alles Vermutungen. Ohne Zugriff auf die Software selbst lässt sich nichts belegen. Aber das für uns sichtbare Fehlerbild passt eben genau in ein Muster.

Hinterlasse einen Kommentar

Diese Seite verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden..