Der moderne Transaktionsstapel

Der moderne Transaktionsstapel

Der moderne Transaktionsstapel PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Transaktionsdatenbanken sind seit langem die kritischste Komponente des Anwendungsdesigns. Warum? Denn eine stabile Datenbank ist im Allgemeinen der ultimative Durchsetzungspunkt für Korrektheit in einer chaotischen, verteilten Welt. Ohne sie würden wir zu viel und zu wenig bezahlen. Wir würden Fahrer verlieren, die versuchten, vom Flughafen nach Hause zu kommen, und wir würden Artikel in unseren Einkaufswagen verlieren. Unsere Online-Konten würden verloren gehen, dupliziert oder beschädigt und funktionsunfähig werden. 

Tatsächlich war die Transaktionsdatenbank (allgemein als OLTP bezeichnet – kurz für Online Transaction Processing – Datenbank) so zentral für die Anwendungsentwicklung, dass sie im Laufe der Zeit immer mehr Anwendungsfunktionalität beanspruchte. Microservices und andere moderne Anwendungsarchitekturen führten jedoch zu neuen Komplexitäten im Anwendungsdesign: Entwickler mussten Daten über verschiedene Dienste hinweg verwalten und Konsistenz zwischen ihnen sicherstellen, was sie dazu zwang, komplexe Datensynchronisierungs- und Verarbeitungsmechanismen intern zu entwickeln. 

Und so sehen wir als Branche ein zunehmendes Bewusstsein dafür, dass Transaktionsgarantien außerhalb des traditionellen Modells benötigt werden. Wir sehen die Entstehung von Systemen, die starke Transaktionsgarantien über die Datenbank hinaus auf die verteilten Apps selbst ausdehnen

Wir haben diese Lösungen in den letzten Jahren verfolgt. Im Allgemeinen streben sie danach, eine transaktionale Zustandsverwaltung in einer großen verteilten App zu ermöglichen, ohne Herausforderungen bei der Skalierung zu schaffen und gleichzeitig eine moderne Programmierumgebung bereitzustellen. 

Wir finden, dass sich diese Lösungen grob in zwei Kategorien unterteilen lassen. Eine Kategorie ist Workflow-Orchestrierung. Dies garantiert im Grunde, dass ein Codeblock vollständig ausgeführt wird, selbst im Falle eines Fehlers. Es kann also verwendet werden, um eine verteilte Zustandsmaschine deterministisch zu verwalten, ohne wackelig zu werden. Die zweite Kategorie ist Datenbank + Workflow, das das traditionelle OLTP-Datenbankdesign erweitert und die Ausführung beliebigen Codes für denselben Zweck ermöglicht. 

Dies ist noch ein sehr junges Gebiet, und es gibt viel Verwirrung in Bezug auf die Nomenklatur, wie die einzelnen Tools in der Praxis verwendet werden und wer sie verwenden sollte. Um ein besseres Verständnis zu erlangen, haben wir Praktiker führender technischer Organisationen nach ihrem Transaktions-Stack gefragt und wie sie über drei Schlüsselkonzepte für Transaktions-Workloads denken: Anwendungsstatus, Geschäftslogik und Geschäftsdaten. 

Bevor wir uns diese neuen Stacks ansehen, hier ein kurzer halbtechnischer Exkurs, um zu verstehen, wie wir hierher gekommen sind.

Transaktionen, Garantien und moderne Apps 

Die sehr grobe Version ist diese: Es gibt eine Reihe von Aufgaben – Transaktionen – die Sie entweder alle oder keine erledigen möchten. Alles dazwischen (wenn es teilweise erledigt ist) endet in einem korrupten Zustand. Es ist schwer zu garantieren etwas in einem verteilten System, aber Datenbanken machen es gut mit Transaktionen. Daher besteht der einfachste Weg, Garantien in vielen Systemen zu handhaben, darin, die meisten Transaktionen einfach durchzuführen und die Datenbank sie verarbeiten zu lassen.

Moderne Apps sind große verteilte Systeme mit vielen Benutzern, die viele Dinge tun. So wird sogar die Konsistenz des App-Status (wie das Verfolgen, wo sich verschiedene Benutzer in einem Check-out-Fluss befinden) zu einem verteilten Transaktionsproblem. In herkömmlichen monolithischen Architekturen war die Verwaltung von Transaktionen mithilfe von SQL mit einer OLTP-Datenbank einigermaßen effektiv. Aber in der neuen, komplexen Welt der Microservices, die über APIs auf höherer Ebene (z. B. REST oder gRPC) interagieren, sind Transaktionsanforderungen in der Natur verteilt geworden. 

Viele Unternehmen, die sich auf den Weg zu Microservices machen, haben jedoch nicht viel getan, um starke Transaktionsgarantien über die Datenbank hinaus auszudehnen. Und in der Praxis ist das so fast immer OK. Aber wenn Anwendungen skalieren, nehmen die Inkonsistenzen in den Daten zu, ebenso wie die daraus resultierende Fehlerhaftigkeit und nicht abgeglichene Fehler in den Geschäftsdaten. Was natürlich sehr problematisch sein kann. Dies zwingt Anwendungsentwickler, sich mit einer Vielzahl von Fehlerszenarien und Konfliktlösungsstrategien auseinanderzusetzen und die Zustandskonsistenz sicherzustellen, indem sie ihre eigenen Strategien durch unterschiedliche Architekturmuster entwickeln.

Definitionen

Geschäftsdaten („Daten“) bezieht sich auf die geschäftskritischen Daten, die traditionell in einer OLTP-Datenbank zur Persistenz und Verarbeitung gespeichert werden (z. B. Benutzerprofilinformationen wie Name, Adresse, Kreditwürdigkeit usw.).

Bewerbungsstatus bezieht sich auf den aktuellen Zustand des Systems; der Anwendungsstatus wird durch einen in einem Datenspeichersystem gespeicherten Wert bestimmt und in welchem ​​Schritt sich die Programmausführung in einer endlichen Zustandsmaschine befindet (z. B. der Status einer Bestellung, wie „Bestellung erhalten“, „Bestand geprüft“, „Kredit geprüft“. “, „versendet“, „zurückgeschickt“).

Geschäftslogik bezieht sich auf den Teil des Programms, der sich damit befasst, wie die Anwendung tatsächlich funktioniert oder was sie tut, anstelle von Ausführungsdetails (z. B. „Wenn Nutzer_Einkommen > $100 & Kredit_Score >650 ⇒ Hypothek_genehmigt = TRUE“).

Für die Zwecke dieser Diskussion ist es wichtig, Anwendungsstatus und Geschäftsdaten zu unterscheiden. Zum Beispiel ist das Wissen, dass ein Kunde seine Kreditkarte eingegeben, aber nicht ausgecheckt hat, der Anwendungsstatus. Geschäftsdaten sind die Daten der Kreditkarte und die Artikel im Warenkorb. 

Der moderne Transaktionsstapel PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

In einem typischen Ablauf kommt eine Anfrage vom Front-End, wird authentifiziert und dann über ein API-Gateway oder GraphQL an den entsprechenden Endpunkt weitergeleitet. 

Dieser einzelne API-Endpunkt muss nun Dutzende oder Hunderte von Microservices orchestrieren, um die Geschäftstransaktion an den Endkunden zu liefern. Hier packen Entwickler normalerweise alles in Geschäftslogik-Blobs und verwenden dann eine Kombination aus Warteschlangen, Caches und handcodierten Wiederholungsmechanismen, um die Daten in die Datenbank zu bringen – hoffentlich als vollständige Transaktion.

Mit zunehmender Größe der Anwendung steigt auch die Komplexität der Verwaltung von Warteschlangen und Caches sowie die Anzahl scharfer Kanten in der Abstimmungslogik, wenn Probleme auftreten. 

Der Aufstieg von Workflow-zentrierten und Datenbank-zentrierten Transaktions-Stacks

OK, Transaktionen sind also wichtig. LAMP in einer Datenbank war für die Skalierung nicht ausreichend. Und ein riesiger Haarball aus Warteschlangen und Wiederholungslogik ist zu spröde. Um damit umzugehen, haben wir in den letzten Jahren das Aufkommen neuer Lösungen gesehen, die der Transaktionslogik wieder Vernunft verleihen. Sie können grob entweder als Workflow-zentrierte Ansätze oder als Datenbank-zentrierte Ansätze kategorisiert werden.

Bisher arbeiten Workflow-Engines hauptsächlich mit dem Anwendungsstatus und nicht mit den Geschäftsdaten und erfordern oft eine gewisse Komplexität bei der Integration mit herkömmlichen Datenbanken. Datenbankzentrierte Ansätze fügen neben Geschäftsdaten auch Anwendungslogik hinzu, verfügen aber noch nicht über die gleiche ausgeklügelte Codeausführung wie Workflow-Engines. 

Das folgende Diagramm bietet eine grobe Skizze, wie Workflow- und/oder datenbankzentrierte Ansätze in einer Javascript-/Typescript-Anwendung verwendet werden, vorausgesetzt, beide werden verwendet. Während sie heute unterschiedliche Teile dieser Architektur sind, haben wir erste Anzeichen eines Trends gesehen, bei dem Datenbanken Workflow-Funktionen integrieren und Workflows beginnen, dauerhafte Speicherung einzuführen. Diese Verschmelzung von Fähigkeiten weist darauf hin, dass die Grenzen zwischen den beiden Ansätzen in modernen Architekturen verschwimmen und weniger deutlich werden. 

Der moderne Transaktionsstapel PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Workflow-zentrierte Ansätze im Detail 

Ein Workflow besteht einfach aus Codeblöcken, die basierend auf Ereignissen oder Timern ausgeführt werden, die die Zustandsmaschine der Anwendung weiterentwickeln. Der transaktionale Workflow stellt die Codeausführung mit starken Garantien sicher und verhindert partielle oder unbeabsichtigte Zustände in der Anwendung. Entwickler schreiben die Logik und die Workflow-Engine verarbeitet Transaktionen, Mutationen und Idempotenz. Unterschiedliche Workflow-Engines treffen unterschiedliche Kompromisse in Bezug darauf, wie viele Transaktionsdetails den Entwicklern offengelegt werden. 

Als Beispiel sehen Sie unten eine visuelle Darstellung eines Check-out-Workflows, der auf Orkes (Conductor) ausgeführt wird: 

Der moderne Transaktionsstapel PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Es gibt zwei grobe Ansätze wodurch Workflow-Engines an Zugkraft gewinnen. In einem (typisiert durch Temporal.io) schreiben Entwickler Code mit Standard-Back-End-Programmiersprachen (z. B. Go oder Java) und dem Das System stellt sicher, dass der Code vollständig ausgeführt wird, auch während eines Ausfalls. In diesem Modell wird der Programmaufruf-Stack beibehalten, selbst wenn der Code darauf wartet, dass ein blockierender Aufruf abgeschlossen wird (z. B. Lesen oder Schreiben). Zu diesem Zweck wird die Sprachlaufzeit geändert, um eine teilweise Codeausführung bei Fehlern zu verhindern. Der Vorteil dieses Ansatzes besteht darin, dass Entwickler in vertrauten Sprachen schreiben und mit einem verwalteten Aufrufstapel problemlos debuggen können. Wir sehen diesen Ansatz am beliebtesten bei Back-End-Teams, die sich mit großen, anspruchsvollen Apps befassen. 

Der Nachteil ist, dass es oft viel Integrationsarbeit und Wrapper-Code erfordert, um nützliche und sichere Schnittstellen für Anwendungsentwickler verfügbar zu machen. Ein weiterer Nachteil besteht darin, dass es auf einer benutzerdefinierten Ausführungsebene und nicht auf der reinen Sprache basiert, und es gibt Grenzfälle, in denen sich die Ausführung von der nativen Sprachlaufzeit unterscheidet. Während Entwickler also Sprachen verwenden können, mit denen sie vertraut sind, müssen sie dennoch verstehen, wie das zugrunde liegende System funktioniert.  

Der andere Ansatz, der bei Anwendungsentwicklern beliebter ist (insbesondere Typescript/Javascript), betrifft die Workflow-Engine dienen als Orchestrator von asynchronen Funktionen (z. B. Ingest, Defer und Trigger). In diesem Modell werden Ereignisse oder Funktionen von Drittanbietern an die Workflow-Engine geleitet, die dann die von den Anwendungsprogrammierern registrierte Logik versendet, die die Kontrolle zurückgeben müssen, sobald die Notwendigkeit besteht, eine andere asynchrone Funktion zu blockieren. Der Vorteil ist, dass dies eine weitaus leichtere Methode zur Integration in ein Programm ist. Es zwingt dem Code auch genügend Struktur auf, damit das Team, das daran arbeitet, ihn leichter verstehen kann. Dieser Ansatz kann jedoch ohne Toolunterstützung schwieriger zu debuggen sein, sodass das Debuggen tendenziell plattformspezifisch ist.

Workflow-Engines sind insofern besonders leistungsfähig, als sie eine schrittweise Übernahme durch bestehende Apps ermöglichen. Sie können stückweise auf bestimmte Workflows mit minimalem Platzbedarf angewendet werden. Allerdings ergeben sich die beiden größten Mängel von Workflow-Engines aus der Tatsache, dass sie sich nicht in die Datenbank erstrecken. Infolgedessen gibt es keine einzige abfragbare Quelle der Wahrheit über den Anwendungsstatus und die Geschäftsdaten. Außerdem unterscheidet sich die Transaktionssemantik im Allgemeinen von der Datenbanksemantik, sodass Anwendungsentwickler Edge-Bedingungen handhaben müssen. 

Obwohl heute nicht mehr üblich, möchten wir die konzeptionellen Architekturen veranschaulichen, wie Workflows in vielen Fällen als persistente Datenspeicher verwendet werden können:

Beispiele für Nur-Workflow-Architekturen

Der moderne Transaktionsstapel PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Nur-Workflow-Architektur: JavaScript-Apps

Der moderne Transaktionsstapel PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Nur-Workflow-Architektur: Apps, die Microservices verwenden

Datenbankzentrische Ansätze im Detail 

Datenbankzentrierte Ansätze beginnen mit einer Datenbank, erweitern sie aber, um die Ausführung beliebigen Codes zu unterstützen, um Arbeitsabläufe neben der Datenverwaltung zu ermöglichen. Sie tun dies, indem sie den Programmierern die Kontrolle geben, damit sie explizite Entscheidungen über Mutationen, Transaktionen und Idempotenz für reguläre Codeblöcke treffen können – im Wesentlichen durch die direkte Offenlegung der OLTP-Semantik. Der Programmierer ist dafür verantwortlich, Geschäftslogik und Geschäftsdaten vom Anwendungszustand getrennt zu halten. 

Tatsächlich ist die reine Datenbanksicht, dass der Anwendungszustand immer aus den Geschäftsdaten abgeleitet werden kann. Dies erfolgt normalerweise durch Speichern des Anwendungsstatus als eine Reihe von Transaktionen, die Geschäftsdaten in der Datenbank ändern. Es ist am einfachsten, sich dies als eine Datenbank vorzustellen, die Codeblöcke mit den gleichen starken Garantien wie die oben beschriebenen Workflow-Systeme ausführen kann. 

Intern nennen wir dies die Anwendungslogik-Transaktionsplattform (ALTP) Ansatz, weil er letztendlich OLTP-Transaktionen in die Anwendung ausdehnt. Aber was ALTP wirklich auszeichnet, ist, dass es für Greenfield-Apps die Notwendigkeit für die App-Entwickler vollständig beseitigen kann, die Back-End-Infrastruktur direkt zu verwalten.  

Von der ALTP-Linse aus begann der am häufigsten verwendete Ansatz mit Firebase, das a Full-Service-Back-End-Erfahrung, einschließlich Authentifizierung, Datenspeicher, Datenbanken und mehr. Firebase und neuere Marktteilnehmer wie Supabase bleiben sehr beliebte Plattformen für Greenfield-Projekte. Und während sie dazu neigen, ihren OLTP-Wurzeln treu zu bleiben – und daher keine willkürliche Codeausführung für transaktionale Backend-Funktionen unterstützen – beginnt Supabase bereits damit, Unterstützung für Workflows hinzuzufügen.

Aber, ALTP-Angebote der nächsten Generation wie Convex erlauben die Ausführung von beliebigem Code als Transaktion neben der Datenbank. Diese Angebote ermöglichen das Schreiben von vollständig transaktionskonformem Code in einer normalen Sprache (z. B. Javascript/Typescript), wobei ein einziger Codeblock Daten lesen, schreiben und mutieren kann – sowohl Anwendungsstatus als auch Geschäftsdaten. In gewissem Sinne bietet es Entwicklern eine einzige abfragbare Quelle der Wahrheit und stellt Workflow-Grundelemente wie Abonnements bereit. 

ALTP löst das Problem, dass Workflow-Engines von der Datenbank entkoppelt sind, aber im Ergebnis verlangen, dass sich die Benutzer auf ihr Datenbankangebot statt auf ein Standard-OLTP verlassen, um die Vorteile zu nutzen. Infolgedessen sehen wir in erster Linie, dass Teams ALTP für Greenfield-Apps übernehmen, anstatt es in bestehende, komplexe Backends zu integrieren.

Der moderne Transaktionsstapel PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Das obige Diagramm ist eine Mischung aus den vielen Operatoren, mit denen wir gesprochen haben. Einige verwenden nur eine Workflow-Engine. Einige verwenden nur einen datenbankzentrierten Ansatz. Viele werden jedoch beide verwenden – insbesondere, wenn sie gerade erst anfangen, Workflows einzuführen. Benutzer von Workflow-Engines sind heute in der Regel Back-End-Teams, die sich mit großen, komplexen Anwendungen befassen, obwohl wir auch gesehen haben, dass viele Full-Stack-Teams sie übernommen haben. Back-End-as-a-Service-Lösungen sind in der Regel anwendungsentwicklerfreundlicher und werden häufiger verwendet, wenn die App die Technologieauswahl vorantreibt. 

Die Konvergenz

Es zeichnet sich ab, dass sich Workflow-zentrierte Ansätze und datenbankzentrierte Ansätze auf Kollisionskurs befinden. Der Hauptgrund dafür ist, dass Anwendungsstatus und Datenbankstatus zwar logisch voneinander getrennt sind, aber voneinander abhängig sind und ein System, das beide nicht abdeckt, komplex zu finden und zu debuggen ist.  

Betrachten Sie als Beispiel eine Workflow-Engine, die verwendet wird, um die Zustandsmaschine für den Checkout-Prozess eines Benutzers zu verfolgen, und dieser Benutzer fügt einen Artikel zu einem Einkaufswagen hinzu. In der Regel stellen Workflow-Engines sicher, dass ein Codeschritt auch im Falle eines Fehlers ausgeführt wird. Es kann jedoch Fälle geben, in denen die Engine einen bestimmten Schritt während eines Fehlers erneut ausführen muss, weil nicht ganz sicher ist, ob der Schritt vollständig abgeschlossen wurde. Wenn dieser Schritt das Schreiben von Geschäftsdaten in eine herkömmliche Datenbank (in diesem Fall den Artikel im Einkaufswagen) beinhaltet und die Datenbank die doppelte Wiederholung nicht kennt, wird sie mit einem doppelten Eintrag enden. 

Es gibt zwei Möglichkeiten, damit umzugehen. Eine Möglichkeit besteht darin, das Problem an den Anwendungsentwickler weiterzuleiten, der eine vom Workflowsystem bereitgestellte Nonce verwendet, um sicherzustellen, dass nur ein Element geschrieben wird. Aber das setzt voraus, dass der Entwickler Idempotenz versteht, was bekanntermaßen schwierig ist, richtig zu machen, und dies verhindert einen Großteil der Magie, die ein Workflow-System mit sich bringt. Die andere Möglichkeit besteht darin, die Workflow-Engine an eine Datenbank zu binden, die die transaktionale Semantik des Workflows kennt. Dies ist noch nicht ganz geschehen, aber es ist nicht schwer zu glauben, dass es passieren wird. 

Andererseits erkennen datenbankzentrierte Ansätze, dass allgemeine Arbeitsabläufe für Anwendungsentwickler wirklich nützlich sind. Und so fangen wir an, Datenbanken (wie Convex) – die traditionelle Datenbankfunktionen wie Abfragen, Mutationen, Indizes usw. unterstützen – Funktionen wie Planung und Abonnements zu implementieren. Dadurch können sie als Workflow-Engines verwendet werden. Das heißt, sie ermöglichen die Ausführung beliebiger Codeblöcke mit starken Garantien. 

Wie Ian Livingstone (der Feedback zu diesem Stück gab) es ausdrückte: „Es ist der Klassiker „Bringen Sie die Anwendungslogik zur Datenbank oder die Datenbank zur Anwendungslogik?“. wieder spielen … dieses Mal durch das Aufbrechen des Monolithen herbeigeführt.“ Nach Jahrzehnten dieser Dichotomie ist klar, dass beide Modelle kurzfristig Bestand haben werden. Weit weniger klar ist, dass dies auf lange Sicht so bleiben wird. 

Besonderer Dank geht an Charly Poly (Defer), Dan Farrelly (Inngest), David Khourshid (Stately), Ian Livingstone (Cape Security), Enes Akar (Upstash), James Cowling (Convex), Jamie Turner (Convex), Paul Copplestone (Supabase ), Sam Lambert (PlanetScale), Tony Holdstock-Brown (Inngest), Matt Aitken (Trigger) für die Überprüfung dieses Beitrags und das Feedback. Außerdem danke ich Benjamin Hindman (Reboot), Fredrik Björk (Grafbase), Glauber Costa (Chiselstrike), Guillaume Salles (Liveblocks), Maxim Fateev (Temporal), Steven Fabre (Liveblocks) und Viren Baraiya (Orkes) für ihre Hilfe die Forschung.

* * *

Die hier geäußerten Ansichten sind die der einzelnen zitierten Mitarbeiter von AH Capital Management, LLC („a16z“) und nicht die Ansichten von a16z oder seinen verbundenen Unternehmen. Bestimmte hierin enthaltene Informationen stammen aus Drittquellen, einschließlich von Portfoliounternehmen von Fonds, die von a16z verwaltet werden. Obwohl sie aus als zuverlässig erachteten Quellen stammen, hat a16z solche Informationen nicht unabhängig überprüft und gibt keine Zusicherungen über die dauerhafte Genauigkeit der Informationen oder ihre Angemessenheit für eine bestimmte Situation. Darüber hinaus kann dieser Inhalt Werbung von Drittanbietern enthalten; a16z hat solche Anzeigen nicht überprüft und unterstützt keine darin enthaltenen Werbeinhalte.

Dieser Inhalt wird nur zu Informationszwecken bereitgestellt und sollte nicht als Rechts-, Geschäfts-, Anlage- oder Steuerberatung angesehen werden. Sie sollten diesbezüglich Ihre eigenen Berater konsultieren. Verweise auf Wertpapiere oder digitale Vermögenswerte dienen nur der Veranschaulichung und stellen keine Anlageempfehlung oder ein Angebot zur Erbringung von Anlageberatungsdiensten dar. Darüber hinaus richtet sich dieser Inhalt nicht an Anleger oder potenzielle Anleger und ist nicht für die Verwendung durch diese bestimmt, und es darf unter keinen Umständen darauf vertraut werden, wenn eine Entscheidung getroffen wird, in einen von a16z verwalteten Fonds zu investieren. (Ein Angebot zur Investition in einen a16z-Fonds wird nur durch das Privatplatzierungsmemorandum, den Zeichnungsvertrag und andere relevante Unterlagen eines solchen Fonds abgegeben und sollte vollständig gelesen werden.) Alle erwähnten, erwähnten oder erwähnten Investitionen oder Portfoliounternehmen oder Portfoliounternehmen Die beschriebenen Investitionen sind nicht repräsentativ für alle Investitionen in von a16z verwaltete Vehikel, und es kann nicht garantiert werden, dass die Investitionen rentabel sind oder dass andere Investitionen in der Zukunft ähnliche Merkmale oder Ergebnisse aufweisen werden. Eine Liste der Investitionen von Fonds, die von Andreessen Horowitz verwaltet werden (mit Ausnahme von Investitionen, für die der Emittent a16z keine Genehmigung zur öffentlichen Offenlegung erteilt hat, sowie unangekündigte Investitionen in öffentlich gehandelte digitale Vermögenswerte) ist unter https://a16z.com/investments verfügbar /.

Die darin bereitgestellten Diagramme und Grafiken dienen ausschließlich zu Informationszwecken und sollten bei Anlageentscheidungen nicht als verlässlich angesehen werden. Die Wertentwicklung in der Vergangenheit ist kein Hinweis auf zukünftige Ergebnisse. Der Inhalt spricht nur zum angegebenen Datum. Alle Prognosen, Schätzungen, Prognosen, Ziele, Aussichten und/oder Meinungen, die in diesen Materialien geäußert werden, können ohne Vorankündigung geändert werden und können von den Meinungen anderer abweichen oder ihnen widersprechen. Weitere wichtige Informationen finden Sie unter https://a16z.com/disclosures.

Zeitstempel:

Mehr von Andreessen Horowitz