Skip to content

Add support for attribute deletion in DynamoDbTable.updateItem when using IgnoreNullsMode.SCALAR_ONLY #6468

@fpezzoni

Description

@fpezzoni

Describe the feature

The DynamoDbTable.updateItem method provides two modes for handling null values via the IgnoreNullsMode setting:

  • IgnoreNullsMode.DEFAULT: Attributes with null values are removed, resulting in a full item update (the entire item must be specified).
  • IgnoreNullsMode.SCALAR_ONLY: Attributes with null values are ignored, allowing a partial update where only the provided attributes are written.

While partial updates are efficient and convenient, since they only write the modified fields, they currently do not support attribute deletion. The only way to delete an attribute is by using IgnoreNullsMode.DEFAULT, which forces a full item overwrite and requires all existing attributes to be specified, even when only a few need updating. In practice, this means the existing item must first be retrieved from DynamoDB before performing the update, so that all current attributes can be included in the overwrite request.

This limitation becomes especially problematic for items with a large number of attributes, where a full update incurs unnecessary read and write overhead, adds latency, and increases code complexity.

Use Case

Consider a BigItem entity with a large number of attributes (e.g., 50 fields such as attr1, attr2, …, attr50):

@Getter
@Builder(toBuilder = true)
@DynamoDbImmutable(builder = BigItem.BigItemBuilder.class)
public class BigItem {

    @Getter(onMethod_ = @DynamoDbPartitionKey)
    private final String id;

    private final String attr1;
    private final String attr2;
    private final String attr3;
    // More attributes to make the item "big"
    private final String attr50;
}

Suppose we need to remove attr3.

With the current API, this requires first retrieving the existing item from DynamoDB, and then performing a full item update using IgnoreNullsMode.DEFAULT, meaning all other attributes must be re-specified, even if they have not changed:

BigItem bigItem = dynamoDbTable.getItem(
    b -> b.key(k -> k.partitionValue(id).build()));

BigItem fullUpdate = bigItem.toBuilder()
    .attr3(null)
    .build();

dynamoDbTable.updateItem(
    b -> {
        b.item(fullUpdate);
        b.ignoreNullsMode(IgnoreNullsMode.DEFAULT);
    }
);

While it is technically possible to remove a single attribute using a low-level UpdateItemRequest with DynamoDbClient, constructing the appropriate update expression becomes cumbersome, especially in more complex scenarios where both attribute updates and deletions must occur together.

Proposed Solution

Introduce support for fields of type Optional<T> within the enhanced client data model.

When performing a partial update with IgnoreNullsMode.SCALAR_ONLY:

  • Attributes with null values would continue to be ignored (unchanged behavior).
  • Attributes with Optional.empty() would be removed from the item.

In the case of a full update, both null and Optional.empty() should indicate that the corresponding attribute must be deleted.

This approach enables developers to explicitly mark attributes for deletion without requiring a full item overwrite, while maintaining backward compatibility with existing behavior.

Example:

@Getter
@Builder(toBuilder = true)
@DynamoDbImmutable(builder = BigItem.BigItemBuilder.class)
public class BigItem {

    @Getter(onMethod_ = @DynamoDbPartitionKey)
    private final String id;

    private final String attr1;
    private final Optional<String> attr2;
    private final Optional<String> attr3;
    // More attributes to make the item "big"
    private final String attr50;
}

In this example, we assume that attr2 and attr3 are nullable fields represented as Optional<String>. If we want to delete attr3, we can explicitly set it to Optional.empty() in a partial update:

BigItem partialUpdate = BigItem.builder()
    .id(id)
    .attr3(Optional.empty())
    .build();

dynamoDbTable.updateItem(
    b -> {
        b.item(partialUpdate);
        b.ignoreNullsMode(IgnoreNullsMode.SCALAR_ONLY);
    }
);

This approach allows clear intent for attribute deletion within partial updates, without needing to retrieve or rewrite the full item.

Other Information

No response

Acknowledgements

  • I may be able to implement this feature request
  • This feature might incur a breaking change

AWS Java SDK version used

2.33.1

JDK version used

21.0.3

Operating System and version

Ubuntu 24.04

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature-requestA feature should be added or improved.needs-triageThis issue or PR still needs to be triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions