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)
}
}Explanation
types.ReturnValueAllOldis a typed constant, not the string"ALL_OLD"— the field takes atypes.ReturnValue, so a typo is a compile error instead of a runtimeValidationException.DeleteItemaccepts onlyNONEandALL_OLD; the rest of the enum is shared withUpdateItem.len(out.Attributes) == 0is 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.As—var ccfe *types.ConditionalCheckFailedExceptionthenerrors.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.ReturnValuesOnConditionCheckFailureAllOldandccfe.Itemholds 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.
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
- DynamoDB DeleteItem in Java — the same delete with AWS SDK for Java 2.x.
- DynamoDB PutItem in Go — the write side of the same key.
- DynamoDB condition expressions — guard deletes with
attribute_existsand value checks. - DynamoDB ConditionalCheckFailedException — what a failed conditional delete throws, and when it's expected.
References
- DeleteItem — Amazon DynamoDB API Reference
- Use DeleteItem with an AWS SDK or CLI — Amazon DynamoDB Developer Guide
- dynamodb package — AWS SDK for Go v2 (pkg.go.dev)
- dynamodb/types package — AWS SDK for Go v2 (pkg.go.dev)
- Condition expressions — Amazon DynamoDB Developer Guide
Last verified 2026-07-28 against the official AWS documentation linked above.