Skip to main content
Skip to main content
Still in beta — questions, comments or suggestions? aramb@aramb.dev

Add Delete Support and Keep the Dashboard in Sync

Add a delete endpoint for uploaded files, removing them from both S3 and DynamoDB, and keep your frontend dashboard updated.

30 min
Introductory
AWS Free TierFREE TIER

All services used in this lesson are covered by the AWS Free Tier.

AWS Services Used

S312-month free tierLambdaAlways free tierDynamoDBAlways free tierAPI Gateway12-month free tier

Learning Outcomes

By the end of this lesson, you will be able to:

  1. Add a delete endpoint for uploaded files.
  2. Delete the S3 object and its DynamoDB metadata record from Lambda.
  3. Explain why the API route should use an HTTP DELETE method.
  4. Update the frontend so the list and detail view stay in sync after deletion.
  5. Explain the importance of deleting from both storage and metadata.

The Core Idea

Your dashboard can already upload files, store metadata, list files, and open individual files. The next logical step is delete support: when a user deletes a file, your backend should remove the object from S3 and remove the matching metadata row from DynamoDB.

Serverless Delete Lifecycle

Important Assumption

For this lesson, assume your upload bucket is not using S3 versioning. In a versioning-enabled bucket, deleting the current object without specifying a version ID does not permanently remove all versions. Instead, S3 creates a delete marker, which changes the behavior from the simpler case.


Why Delete Both Places?

If you delete only the S3 object and keep the DynamoDB item, your dashboard will show stale metadata. If you delete only the DynamoDB item and keep the S3 object, the file still exists in storage even though your UI no longer knows about it.


Part 1: Add the API Route

Create a new HTTP API route: DELETE /metadata. API Gateway HTTP API routes are defined by an HTTP method plus a resource path.


Part 2: Update API CORS

Because your browser frontend will now send a DELETE request, your HTTP API CORS configuration must allow the DELETE method.

Update your settings to allow:

  • Allowed Origins: Your frontend origin
  • Allowed Methods: GET, POST, DELETE
  • Allowed Headers: Content-Type

Part 3: Create the Delete Lambda Function

Create a new Lambda function with environment variables TABLE_NAME and UPLOAD_BUCKET. Use this Python code:

import json
import os
import boto3

s3_client = boto3.client("s3")
dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table(os.environ["TABLE_NAME"])
upload_bucket = os.environ["UPLOAD_BUCKET"]

def lambda_handler(event, context):
    try:
        body = json.loads(event.get("body") or "{}")
    except json.JSONDecodeError:
        return {
            "statusCode": 400,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps({"error": "Invalid JSON body"})
        }

    bucket = body.get("bucket")
    object_key = body.get("key")

    if not bucket or not object_key:
        return {
            "statusCode": 400,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps({"error": "Missing required fields: bucket and key"})
        }

    if bucket != upload_bucket:
        return {
            "statusCode": 400,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps({"error": "Bucket does not match configured upload bucket"})
        }

    # 1. Delete from S3
    s3_client.delete_object(
        Bucket=bucket,
        Key=object_key
    )

    # 2. Delete from DynamoDB
    table.delete_item(
        Key={
            "bucket": bucket,
            "object_key": object_key
        }
    )

    return {
        "statusCode": 200,
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps({
            "message": "Deleted successfully",
            "bucket": bucket,
            "object_key": object_key
        })
    }

Part 4: Give the Function Permissions

The function needs permission to delete both the S3 object and the DynamoDB row.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DeleteUploadedObjects",
      "Effect": "Allow",
      "Action": ["s3:DeleteObject"],
      "Resource": "arn:aws:s3:::YOUR_UPLOAD_BUCKET/incoming/*"
    },
    {
      "Sid": "DeleteMetadataItems",
      "Effect": "Allow",
      "Action": ["dynamodb:DeleteItem"],
      "Resource": "arn:aws:dynamodb:REGION:ACCOUNT_ID:table/upload_metadata"
    }
  ]
}

Part 5: Frontend Integration

Update your frontend to include a deleteFile function using the DELETE method. The simplest UI strategy after a successful deletion is to reload the list. This ensures the UI accurately reflects the source of truth on the backend.


Part 6: Test the Full Flow

  1. Load your uploaded file list.
  2. Open details for one file.
  3. Click Delete and confirm.
  4. Verify the file disappears from the list and the detail panel is cleared.

Lab Checklist

StepSuccess Condition
Create DELETE routeRoute exists in HTTP API
Add Lambda integrationAPI requests reach the delete function
Add s3:DeleteObject permissionLambda can remove the S3 object
Add dynamodb:DeleteItem permissionLambda can remove the metadata row
Update frontendDelete button appears and works
Refresh listDeleted file disappears from UI

Micro-activity 1: Reflection

Think about it

After the lab, reflect: Which object key did you delete? Did the API return success or an error? Did the item disappear from the list? When you refreshed the page, was the file still gone?


Micro-activity 2: Consistency Rule

Think about it

Why is deleting both the S3 object and the DynamoDB metadata row better than deleting only one? Why is reloading the list after delete a good UI strategy?


Summary

In this lesson, you added delete support to the upload dashboard. You learned that API Gateway routes by method and path, and that staying in sync requires removing data from both storage (S3) and metadata (DynamoDB).


Quiz

Knowledge Check
1 / 5

Which HTTP method is the best fit for this delete route?