GraphQL Cascade Deletion with AWS Amplify

Paulo Pires
3 min readJul 7, 2021

This is one way to deal with delete mutations on the source type of one-to-many relationships in your GraphQL schema, so you won’t remain with any orphan records.

Photo by Leo Rivas on Unsplash

If you ever had to delete a source type record in a one-to-many relationship, you know that you have to manually delete the target type associated records, otherwhise those records will become orphans in your database.

Let’s take Amplify’s GraphQL example, where you have Blogs, Posts and Comments:

Let’s say you want to delete a Blog. Before doing that, you must run a query that gets the children Posts and Comments, because after you delete the Blog you can’t find them anymore (not with the GraphQL queries), even if you have the Blog’s ID.

Of course this function shouldn't run client side, because it could be interrupted before it finishes running the multiple delete mutations.

But what if someone deletes the Blog register directly on the database?

Solution:

On the first place, I recommend using the verbose connection schema described here instead of the one shown in the first example. Actually, it’s almost the default schema if you choose the one-to-many template when adding a GraphQL API to your amplify project. We’re just adding a queryField to the key. This way you can retrieve the children if you have the parent’s ID. The schema could be written this way:

Now we create Lambda Functions that will be triggered when something changes on the database. This function will use a Lambda Layer we have previously created (check my other article here) with GraphQL execution capabilities.

First, create a trigger for the Blog table.

$ amplify add functionSelect which capability you want to add:❯ Lambda function (serverless function)
Lambda layer (shared code & resource used across functions)
Provide an AWS Lambda function name: blogTriggerChoose the runtime that you want to use: .NET Core 3.1
Go
Java
❯ NodeJS
Python
Choose the function template that you want to use: CRUD function for DynamoDB (Integration with API Gateway)
Hello World
❯ Lambda trigger
Serverless ExpressJS function (Integration with API Gateway)
What event source do you want to associate with Lambda trigger?❯ Amazon DynamoDB Stream
Amazon Kinesis Stream
Choose a DynamoDB event source option❯ Use API category graphql @model backed DynamoDB table(s) in the current Amplify project
Use storage category DynamoDB table configured in the current Amplify project
Provide the ARN of DynamoDB stream directly
Choose the graphql @model(s)❯ ◉ Blog
◯ Comment
◯ Post
Do you want to configure advanced settings? yDo you want to access other resources in this project from your Lambda function? ySelect the categories you want this function to have access to. ◯ auth
❯ ◉ api
◯ storage
Select the operations you want to permit on database ◉ Query
❯ ◉ Mutation
◯ Subscription
Do you want to invoke this function on a recurring schedule? nDo you want to enable Lambda layers for this function? yProvide existing layers or select layers in this project to access from this function (pick up to 5): <select the graphql layer you've created>Select a version for graphQl: Always choose latest versionDo you want to configure environment variables for this function? nDo you want to configure secret values this function can access? nDo you want to edit the local lambda function now? y

The function will be executed every time a record is added, deleted or changed in the Blog table. First, we filter the delete mutations only:

Then we create a function to list and remove the children. Note that we just list the Posts and remove them. The Comments will be removed later by another function, triggered when a Post is deleted.

Now you should create another triggered Lambda Function for the Posts and do the same thing, but this time removing the Comments.

That’s it!

--

--