Conditional Requests

Conditional requests provide a way to control whether an action should be executed, based on certain metadata checks associated with an object. Here are some common parameters used for conditional requests:

  • If-Match / If-None-Match:
    These parameters compare the object’s ETag value before allowing an operation.

    • If-Match allows the operation only if the object’s ETag matches the given value.
    • If-None-Match allows the operation only if the object’s ETag does not match the given value.
    • Both parameters also support the wildcard (*), which applies the condition to any ETag.
  • If-Modified-Since / If-Unmodified-Since:
    These parameters compare the object’s last modified date or creation date before proceeding.

    • If-Modified-Since allows the operation only if the object has been modified after the specified date.
    • If-Unmodified-Since allows the operation only if the object has not been modified after the specified date.
  • If-Match-Size / If-Match-Last-Modified-Time:
    These are typically used with DeleteObject operations to check the object’s size or last modified time before deletion.

Conditional request logic can also be enforced at the bucket level through bucket policies. For example, you can configure a policy to prevent accidental data overwrites. For detailed guidance, see Bucket policy How-To.

Use cases for conditional requests include:

  • Preventing conflicts during concurrent object updates
  • Saving bandwidth by avoiding unnecessary data transfers
  • Enabling advanced architectural patterns and workflows 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"
}