AWS AppSync: Zugriff auf DynamoDB ohne Lambda

In einer unserer letzten Kundenprojekte hatten wir die große Freude, eine GraphQL API mit AWS AppSync umsetzen zu dürfen. AWS AppSync ermöglicht uns eine serverless GraphQL API zu bauen und mit Datenquellen zu verknüpfen, wie zum Beispiel mit AWS Lambda, Amazon DynamoDB oder Amazon RDS.

Lambda-orientierte Architekturen

Wenn man von Serverless im Zusammenhang mit AWS spricht, dann ist schnell von AWS Lambda die Rede. Lambda kann man sich wie eine kleine Funktion in der funktionalen Programmierung vorstellen, die vollautomatisch von AWS ausgeführt wird. Damit können wir kleine, gut testbare Einheiten programmieren und müssen uns nicht mehr um das Betreiben einer Web-Applikation kümmern. Eine GraphQL API mit Lambda:

Lambda-orientierte Architekturen

Die Lambda-Funktionen werden in diesem Beispiel immer dann ausgeführt, wenn eine HTTP-Anfrage an das API gestellt wird. So könnte beispielhaft eine Lambda-Funktion aussehen:

const AWS = require("aws-sdk");
const { v4: uuidv4 } = require("uuid");

exports.handler = async (event) => {
  const ddb = new AWS.DynamoDB({ apiVersion: "2012-08-10" });

  return ddb
    .putItem({
      TableName: "USERS",
      Item: {
        id: { S: uuidv4() },
        email: { S: event.arguments.email },
      },
    })
    .promise();
};

Die Lambda-Funktion stellt eine Anfrage an DynamoDB, um eine:n neue:n Nutzer:in anzulegen. Wenn wir nun genauer hinschauen, erkennen wir, dass die Lambda-Funktion nicht das Potenzial einer Programmiersprache nutzt. Im Grunde genommen steckt sie nur eine Anfrage an eine Datenbank zusammen. Könnte man nicht auch eine andere Form schaffen um die Schnittstelle der API mit der Schnittstelle der Datenbank zu verknüpfen?

VTL für triviale Datenbankoperationen

Die Velocity Template Language (VTL) ist eine Template-Sprache, die von AWS AppSync genutzt wird, um Integrationen zwischen zwei Schnittstellen zu beschreiben. Diese Integration wird in JSON beschrieben und kann zum Beispiel so aussehen:

{
  "version": "2017-02-28",
  "operation": "PutItem",
  "key": {
    "id": $util.dynamodb.toDynamoDBJson($util.autoId())
  },
  "attributeValues": {
    "email": $util.dynamodb.toDynamoDBJson($ctx.args.email)
  }
}

Wenn nun eine Anfrage an die API gestellt wird, dann wird keine Lambda-Funktion aufgerufen. AWS steckt die Anfrage an DynamoDB direkt zusammen und baut die Argumente der Anfrage dynamisch ein. Zudem bietet uns AWS AppSync auch praktische Methoden an, womit wir zum Beispiel eine UUID oder auch Zeitstempel generieren können. Wir konnten also mit dieser Variante das selbe Verhalten abbilden wie mit der Lambda-Funktion, doch mit einigen Vorteilen:

  • Weniger Latenz, da die Systemumgebung für eine Lambda-Funktion wegfällt
  • Geringere Kosten, da Lambda pro Ausführung und Dauer bezahlt werden muss
  • Weniger Quellcode bzw. Abhängigkeiten, die wir pflegen müssen

Hybride Lösungen für mehr Flexibilität

Diese direkten Integrationen mit Datenbanken oder auch anderen Services sind hervorragend um triviale Operationen durchzuführen, dennoch ersetzen sie in manchen Fällen nicht den Nutzen von Programmiersprachen. Wenn zum Beispiel Daten validiert werden müssen, dann kann VTL an seine Grenzen kommen. AWS AppSync kann uns dabei unterstützen mit so genannten Pipelines. Mit Pipelines können wir für eine Anfrage mehrere Operationen ausführen:

AWS AppSync Pipeline

Um nun eine:n neue:n Nutzer:in anzulegen, überprüfen wir mit einer Lambda-Funktion ob die angegebenen Daten, wie die E-Mail Adresse oder die Telefonnummer, valide sind. Falls ja, wird die VTL-Integration genutzt um die neue Entität anzulegen.

Fazit

AWS AppSync bietet uns mit direkten Integrationen neue Möglichkeiten, GraphQL APIs zu bauen. So können wir in vielen Fällen auf den Einsatz von Lambda-Funktionen verzichten und damit noch effizienter unsere Geschäftslogik implementieren. Für komplexere Anfragen haben wir weiterhin die Option Lambda-Funktionen zu nutzen und mit VTL-Integrationen zu kombinieren.

Zu diesem Thema haben wir erst kürzlich einen Workshop bei den ServerlessDays Hamburg gegeben. Eine detaillierte Schritt-für-Schritt Anleitung könnt ihr hier finden.

photo of Henrik

Henrik is a Cloud Consultant at superluminar. With his passion for modern software development and sustainable infrastructure, as well as a background as a front-end developer, Henrik covers a broad spectrum. Here he writes about AWS topics, with a focus on serverless.