DEV Community

Cover image for DynamoDB DeleteItem in Go (AWS SDK v2)
DynoTable
DynoTable

Posted on Originally published at dynotable.com

DynamoDB DeleteItem in Go (AWS SDK v2)

client.DeleteItem takes a dynamodb.DeleteItemInput carrying the full primary key. With types.ReturnValueAllOld the response tells you whether anything was actually there; once you add a ConditionExpression, the error tells you why it stayed.

Code

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)

func main() {
    ctx := context.TODO()
    cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1"))
    if err != nil {
        log.Fatalf("load config: %v", err)
    }
    client := dynamodb.NewFromConfig(cfg)

    out, err := client.DeleteItem(ctx, &dynamodb.DeleteItemInput{
        TableName: aws.String("Music"),
        Key: map[string]types.AttributeValue{
            "Artist":    &types.AttributeValueMemberS{Value: "Arturo Sandoval"},
            "SongTitle": &types.AttributeValueMemberS{Value: "Cubano Chant"},
        },
        ReturnValues: types.ReturnValueAllOld,
    })
    if err != nil {
        log.Fatalf("delete item: %v", err)
    }

    if len(out.Attributes) == 0 {
        fmt.Println("No item with that key existed")
    } else {
        fmt.Println("Deleted:", out.Attributes)
    }
}
Enter fullscreen mode Exit fullscreen mode

Explanation

  • types.ReturnValueAllOld is a typed constant, not the string "ALL_OLD" — the field takes a types.ReturnValue, so a typo is a compile error instead of a runtime ValidationException. DeleteItem accepts only NONE and ALL_OLD; the rest of the enum is shared with UpdateItem.
  • len(out.Attributes) == 0 is the only signal you get — deleting a key that was never there succeeds, and the SDK hands back a nil map rather than an error. Nothing else separates "deleted it" from "there was nothing to delete".
  • Match the guard failure with errors.Asvar ccfe *types.ConditionalCheckFailedException then errors.As(err, &ccfe). A direct comparison misses it, because Go v2 wraps service faults in a Smithy operation error.
  • The exception can carry the losing item — set ReturnValuesOnConditionCheckFailure: types.ReturnValuesOnConditionCheckFailureAllOld and ccfe.Item holds the row as DynamoDB saw it, so you can log the value that actually failed the guard instead of re-reading it. The SDK documents the price: "No read capacity units are consumed."
  • One item per call — there is no delete-all API. Deleting many items means collecting the keys first and batching the writes, or dropping the table.

Cost note

DeleteItem consumes 1 WCU per ≤1 KB of the deleted item (rounded up). Confirm item size with the item size calculator before you batch-delete in a loop — a 3 KB item is still 3 WCUs each. On-demand prices those units in us-east-1 the same way as provisioned metering; check the pricing calculator if you are sizing a cleanup job.

Do it visually

The guard is the fiddly half: a ConditionExpression plus the name and value maps that go with it. The DynamoDB Expression Builder assembles all three from a form.

DynoTable attacks the same risk from the other end. A delete lands in a Pending changes panel first and only reaches the table when you commit it, so a wrong row is something you discard rather than something you restore. Download DynoTable.

Related examples

References

Last verified 2026-07-28 against the official AWS documentation linked above.

Top comments (0)