Conditional Requests

Conditional requests are used to determine if an action is to be performed based on a metadata comparison:

  • if-match type of parameters (and its counterpart if-none-match) can be used to check an object against an ETag
    • both if-match and if-none-match parameters can take the wildcard value *
  • if-modified-since type of parameters (and its counterpart, if-unmodified-since) can be used to check an object against a creation date
  • if-match-size and if-match-last-modified-time are used for DeleteObject operations

Conditional requests can also be applied via bucket policies to eg: prevent data overwrite. For an example, please refer to the Bucket policy How-To guide.

Some applications for conditional requests are: handling concurrent requests gracefully, bandwidth savings or to implement exquisite architectural patterns on top of SOS.

Requirements

These parameters are generally available, and need only support from the client (eg: AWS S3 cli, Java SDK, etc). In case of multiple conditional parameters for a single request, SOS follows RFC7232 as closely as possible.

Operations

All examples are assuming you are using the AWS S3 cli, however most S3 clients should have support for conditional requests. Date parameters are formatted as defined by RFC3339 or RFC822:

  • 2025-06-09T15:40:42+00:00
  • Tue, 05 Aug 2025 11:32:21 +0000

get-object

Conditional get requests can be useful when the client may expect an existing object to be in place, and may want to save bandwidth if the client has a local copy.

When retrieving an object, the following parameters can be specified:

  • --if-match <ETag> gets the object if the ETag matches the object ETag
  • --if-none-match <ETag> gets the object if the ETag does not match the object ETag
  • --if-modified-since <Timestamp> gets the object if the object LastModified is equal or after the Timestamp
  • --if-unmodified-since <Timestamp> gets the object if the object LastModified is before the Timestamp

put-object

Conditional put requests can be useful in a high concurrency scenario, where multiple clients can try to upload a given object but only one should succeed.

When uploading an object, the following parameters can be specified:

  • --if-match <ETag> puts the object if the ETag matches the object ETag
  • --if-none-match <ETag> puts the object if the ETag does not match the object ETag

copy-object

Copying an object can accept the following conditional parameters:

  • --copy-source-if-match <ETag> copy if the source object ETag matches the ETag
  • --copy-source-if-none-match <ETag> copy if the source object ETag does not match the ETag
  • --copy-source-if-modified-since <Timestamp> copy if the source object LastModified is equal or after the Timestamp
  • --copy-source-if-unmodified-since <Timestamp> copy if the source object LastModified is before the Timestamp

All the parameters refer to the source object attributes, and are similar to get-object parameters.

delete-object

Conditional deletes can supply the following parameters:

  • --if-match <ETag> object will be deleted if its ETag matches the supplied ETag
  • --if-match-last-modified-time <Timestamp> object will be deleted if its LastModified matches the supplied Timestamp
  • --if-match-size <Size> object will be deleted if its Size matches the supplied Size

Example

Below is an example of using the aws cli to conditionally put or get an object.

# first we put an object
$ aws s3api put-object --bucket my-bucket --key mykey --body /tmp/myobj.bin 

{
    "ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
    "VersionId": "1152004336876784859"
}

# we can ensure we overwrite an object given its ETag
# this can be useful for a client that wants to put only if the object hasn't been modified in the meantime
$ aws s3api put-object --bucket my-bucket --key mykey --body /tmp/myobj.bin --if-match "d41d8cd98f00b204e9800998ecf8427e"
{
    "ETag": "\"323bf3388a58620e50b5b22f550236bb\"",
    "VersionId": "1152004380476574947"
}

# we can also ensure we overwrite anything
$ aws s3api put-object --bucket my-bucket --key mykey --body /tmp/myobj.bin --if-match "*"
{
    "ETag": "\"3cd3e5bf2f0f53862405768788fd17fb\"",
    "VersionId": "1152004396721115840"
}

# a non-matching ETag will fail
$ aws s3api put-object --bucket my-bucket --key mykey --if-match "<some etag>"

An error occurred (PreconditionFailed) when calling the PutObject operation: Your preconditions were not met.


# but a common case is to only put an object if there isn't one
$ aws s3api put-object --bucket my-bucket --key mykey --body /tmp/myobj.bin --if-none-match "*"

An error occurred (PreconditionFailed) when calling the PutObject operation: Your preconditions were not met.


##
# assuming we have a copy of the object, a client may only be interested in getting different or newer versions
$ aws s3api get-object --bucket mybuckey --key mykey --if-none-match "<some old etag>" /tmp/mykey
{
    "AcceptRanges": "bytes",
    "LastModified": "2025-08-06T11:59:15+00:00",
    "ContentLength": 0,
    "ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
    "VersionId": "1152004396721115840",
    "ContentType": "application/binary",
    "Metadata": {}
}

# we can also request an object only if a more recent modification exists
$ aws s3api get-object --bucket mybucket --key mykey --if-modified-since "2025-08-06T11:59:25+00:00" /dev/null

An error occurred (304) when calling the GetObject operation: Not Modified

##
# we can also ask to delete an object only if we match the ETag
# because another client may have updated the object in the meantime
$ aws s3api delete-object --bucket my-bucket --key mykey --if-match "<some old etag>"

An error occurred (PreconditionFailed) when calling the DeleteObject operation: Your preconditions were not met.

# but if the object is still the one the client knows (the etag will match), the object can be safely deleted
$ aws s3api delete-object --bucket my-bucket --key mykey --if-match "d41d8cd98f00b204e9800998ecf8427e"
{
    "DeleteMarker": true,
    "VersionId": "1152006421454263029"
}