Projekt · 2019 · Lead

Elevatus: KI-gestütztes Multi-Tenant-Recruitment-SaaS

Roadmap-Ausführung und Microservices-Migration für Elevatus geleitet - eine Cloud-Recruitment-Plattform für Unternehmen und Regierungen im Nahen Osten.

Client-server architecture diagram showing request-response flow, hero image for architecture topic posts.

Elevatus ist real. Es läuft heute unter elevatus.jobs. Regierungen im Nahen Osten nutzen es für Einstellungsrunden im öffentlichen Dienst. Unternehmen mit einer 1000-köpfigen HR-Operation nutzen es. Beide - verschiedene Tenants, völlig verschiedene Compliance-Envelopes - laufen auf derselben Kernplattform.

Ich war Technical Team Leader und IC Architect im Roadmap-Team bei Talentera (jetzt Elevatus) von 2018 bis 2020. Was ich baute, was ich leitete und wo ich Fehler machte - das ist, worum es in dieser Case Study geht.

Der Ausgangspunkt: TCL/TK auf AOL/Navi-Servern

Nein, das ist kein Tippfehler.

Als ich anfing, lief ein Teil der Codebase noch auf Tcl/Tk auf AOL/Navi-Webservern - ein Stack, der aus dem Support herausfiel, während das Produkt Enterprise-SLAs bedienen sollte. Wir trugen auch einen PHP-7-Monolith, ein wachsendes Vue.js-Frontend und frühe Java-8-Services ohne konsistenten Inter-Service-Contract.

Die Migration war kein Greenfield. Sie ist es nie. Man bedient live Tenants - Regierungsministerien, die keinen Montags-Morning-Ausfall tolerieren - während man gleichzeitig ein System entkoppelt, das nie darauf ausgelegt war, entkoppelt zu werden. Der Ansatz war Strangler-Fig: neue Fähigkeiten landeten von Tag eins als Bounded-Context-Microservices; Legacy-Oberflächen wurden progressiv ersetzt. Die Routing-Schicht (Nginx, später ein API-Gateway) machte die Cuts für Clients unsichtbar.

Domain-Driven Design als Forcing-Function

DDD war die Sprache, mit der wir Service-Grenzen mit dem Product-Team aushandelten. Es war keine akademische Übung - es war der Mechanismus, der Engineers ermöglichte zu sagen “nein, dieses Feature gehört in die Candidate-Domain, und wenn ihr es in die Recruiter-Domain steckt, werden wir zwei Jahre lang daran herumfummeln.” In einer Multi-Produkt-, Multi-Squad-Umgebung ist dieses Vokabular mehr wert als die Architektur-Diagramme.

Die Bounded-Contexts, die entstanden - Candidate, Application, Workflow, Identity, Analytics - wurden sauber auf Team-Ownership gemappt. Wenn ein Regierungs-Client eine angepasste Hiring-Stage wollte, besaß das Workflow-Team das ohne Candidate oder Analytics anzufassen. Das ist der Gewinn, den man anstrebt: Change-Isolation.

Camunda BPMN: Workflows pro Tenant, nicht global

Das ist die Entscheidung, mit der ich aus dieser Zeit am zufriedensten bin.

Recruitment-Workflows sind wirklich variabel. Ein Ministeriums-Civil-Service-Hiring-Flow könnte 14 Stufen, drei Genehmigungsausschüsse und eine gesetzlich vorgeschriebene Wartezeit haben. Der Flow eines Startups könnte 5 Stufen haben und eine Woche laufen. Man kann weder das eine noch das andere hardcoden. Man kann keine Konfigurations-UI bauen, die beides abdeckt, ohne das eine unbrauchbar zu machen.

Was man tun kann: beide als BPMN-Prozessdefinitionen modellieren, sie pro Tenant speichern und auf einer gemeinsamen Camunda-Engine ausführen. Eine neue Workflow-Variante für einen neuen Enterprise-Client hinzuzufügen wurde ein BPMN-Datei-Deployment, kein Sprint. Dieser Satz trägt viel Gewicht, wenn das Sales-Team einem großen Regierungs-Client versprochen hat, dass die Plattform flexibel genug ist, ihre Procurement-Anforderungen zu handhaben.

Die Camunda-Entscheidung gab uns auch Auditierbarkeit umsonst. Regierungs-Clients kümmern sich um Auditierbarkeit auf eine Weise, wie es Enterprise-Clients nicht tun - nicht weil ihre Developer anspruchsvoller wären, sondern weil ihre Legal-Teams es sind. Jeder Workflow-Übergang ist ein Camunda-Event. Der Audit-Trail ist eine Query, keine Forensik-Übung.

Keycloak und das federated-Identity-Problem

Multi-Tenancy wird kompliziert, sobald ein User in mehr als einem Tenant-Kontext existiert.

Im MENA-Recruitment-Markt bewirbt sich ein Kandidat breit. Ein qualifizierter Engineer könnte in drei simultanen Hiring-Runden aktiv sein - eine bei einem Tech-Unternehmen, eine bei einem Regierungsministerium, eine bei einer regionalen Bank - alle auf derselben Plattform. Dieselbe E-Mail-Adresse. Dieselbe Person. Drei vollständig separate Tenant-Kontexte, drei vollständig separate Application-States, und eine explizite Anforderung, dass keiner der drei Tenants wissen kann, dass der Kandidat sich auch bei den anderen bewirbt.

Die Antwort war Keycloak mit Realms pro Tenant und Cross-Realm-Token-Exchange. Das Core-Profil eines Kandidaten lebte in einem geteilten Identity-Space. Seine Application-Daten lebten im Tenant-Realm. Authentifizierung war tenant-scoped - man konnte nicht versehentlich Credentials aus einer Tenant-Session in eine andere mitnehmen. Keycloaks Realm-Federation machte das handhabbar, ohne Identity-Federation von Grund auf zu bauen, was die Art Arbeit ist, die in Jahr zwei Security-Incidents produziert, wenn die Edge-Cases auftauchen.

”KI-gestützt” in 2018, ehrlich

Das Elevatus-Pitch enthielt KI-gestütztes Hiring. Das stimmte. Es war auch etwas komplizierter als es klingt.

GPT-3 existierte nicht. Was wir hatten, war ML-gesteuertes CV-Parsing und -Scoring, Kandidaten-Ranking nach gewichteten Kriterien und frühe Video-Interview-Analyse. Das CV-Parsing war das Stück, das in Produktion gut funktionierte - strukturierte Extraktion aus unstrukturierten Lebensläufen auf Arabisch, Englisch, Französisch und Hindi, normiert in Kandidaten-Profile, die das Ranking-Modell gegen Job-Kriterien scoren konnte.

Die tenant-spezifische Modell-Personalisierung war der architektonisch interessante Teil. Die Recruiter-Entscheidungen eines Regierungsministeriums (Credential-Verifikation und regulatorische Compliance dominieren) formten ein Ranking-Modell, das sich bedeutsam von dem unterschied, das auf den Entscheidungen eines Tech-Unternehmens trainiert war (Portfolio und nachgewiesene Skills dominieren). Das ist das korrekte Ergebnis - aber es ist auch ein Storage- und Serving-Problem, das nicht existiert, wenn man ein globales Modell betreibt. Multi-Tenancy auf ML-Infrastruktur angewendet ist eine eigene Schicht von Constraints.

Die Video-Interview-Analyse funktionierte. Es war aber auch, im Nachhinein, ein System, das viel rigoroseres Bias- und Fairness-Tooling benötigt hätte, als wir 2018 hatten. Unsere Regierungs-Clients verlangten explizite Antworten auf “behandelt dieses Modell Kandidaten über demografische Gruppen hinweg fair” - nicht weil ihre Developer philosophisch ahead of the field wären, sondern weil ihre Diversity-Mandate es zu einer Vertragsfrage machten. “Das Modell hat es gesagt” ist eine Antwort, die ein Ministeriumsbüro nicht akzeptiert. Das lernten wir früh. Das Feld hat seitdem aufgeholt.

Die Mobile-Schicht: was ich anders machen würde

Zuerst Ionic, dann Flutter. Beides waren Adaptionen der Web-Erfahrung auf Mobile, und das war zu sehen.

Kandidaten-Experience auf Mobile - bewerben, Status tracken, Video-Interviews auf dem Telefon machen - hat andere UX-Constraints als Recruiter-Experience auf Desktop: Hunderte von Kandidaten reviewen, Batch-Entscheidungen treffen, Hiring-Runden managen. Wir bauten Mobile als Port. Es war nie so gut, wie ein Produkt gewesen wäre, das Mobile-first designt wurde.

Wenn ich das heute machen würde, wären Kandidaten-UX und Recruiter-UX separate Produkte, die ein Backend teilen. Die API-Schicht wäre von Anfang an mit beiden Consumern im Sinn designt worden. Das ist die API-first-Lektion, die jeder genau einmal auf die harte Tour lernt. Ich habe sie jetzt gelernt.

Was ich verantwortete

  • Roadmap-Ausführung und Sprint-Planning über mehrere Squads
  • DDD-Facilitation und Bounded-Context-Grenzentscheidungen
  • Camunda-BPMN-Integration-Architektur und tenant-spezifisches Workflow-Modell
  • Keycloak-Realm-Federation-Design
  • Microservices-Migrations-Sequenzierung (Strangler-Fig-Ausführung)
  • RabbitMQ-Event-Topologie für Cross-Service-Kommunikation
  • Jenkins-Pipeline-Standardisierung über Squads

Regierungen nutzen das tatsächlich. Dieser Satz landet anders, wenn man den Procurement-Prozess, die Security-Reviews, die Customization-Verhandlungen und die Integration-Arbeit durchlaufen hat, die “tatsächlich nutzen” erfordert. Das ist kein MVP mit einem freundlichen Early-Adopter. Es ist Produktionssoftware, die kritische Prozesse für Institutionen betreibt, die keinen Downtime tolerieren können.

Das haben wir gebaut.