<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ANSHUL VAIBHAV</title>
    <description>The latest articles on DEV Community by ANSHUL VAIBHAV (@anshul_vaibhav_1f725e0621).</description>
    <link>https://dev.to/anshul_vaibhav_1f725e0621</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4190897%2F77a4a219-764a-4517-9622-b0972031567d.png</url>
      <title>DEV Community: ANSHUL VAIBHAV</title>
      <link>https://dev.to/anshul_vaibhav_1f725e0621</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anshul_vaibhav_1f725e0621"/>
    <language>en</language>
    <item>
      <title>S3 Select in 2026: Why New Accounts Get MethodNotAllowed, and What to Use Instead</title>
      <dc:creator>ANSHUL VAIBHAV</dc:creator>
      <pubDate>Fri, 06 Nov 2026 05:58:47 +0000</pubDate>
      <link>https://dev.to/anshul_vaibhav_1f725e0621/s3-select-in-2026-why-new-accounts-get-methodnotallowed-and-what-to-use-instead-ckd</link>
      <guid>https://dev.to/anshul_vaibhav_1f725e0621/s3-select-in-2026-why-new-accounts-get-methodnotallowed-and-what-to-use-instead-ckd</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;S3Object&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was the query I expected to work. I had uploaded a tiny CSV to Amazon S3, checked its metadata, and previewed the contents. When I clicked &lt;strong&gt;Run Query&lt;/strong&gt; in Buckets by Serverless Creed, I got this instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The specified method is not allowed against this resource.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Changing the SQL didn't resolve it. Running the equivalent operation through AWS CLI returned &lt;code&gt;MethodNotAllowed&lt;/code&gt; too.&lt;/p&gt;

&lt;p&gt;This post follows that investigation across four scenarios in &lt;strong&gt;Buckets v2.8.7 and v2.8.9&lt;/strong&gt;. It also explains the S3 Select availability change behind a plausible diagnosis, and the alternatives I would consider for a new project in 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  What S3 Select was designed to do
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/selecting-content-from-objects.html" rel="noopener noreferrer"&gt;S3 Select&lt;/a&gt; lets an application send a SQL expression against &lt;strong&gt;one S3 object&lt;/strong&gt; and receive selected records instead of downloading the entire object first.&lt;/p&gt;

&lt;p&gt;It supports a subset of SQL over CSV, JSON and Apache Parquet inputs, with CSV or JSON output. For example, an application could request particular employee fields or filter records by department.&lt;/p&gt;

&lt;p&gt;The single-object scope matters. A query against &lt;code&gt;S3Object&lt;/code&gt; isn't a query across a bucket or a database of related tables.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed on July 25, 2024
&lt;/h2&gt;

&lt;p&gt;In its &lt;a href="https://aws.amazon.com/blogs/storage/how-to-optimize-querying-your-data-in-amazon-s3/" rel="noopener noreferrer"&gt;July 2024 announcement&lt;/a&gt;, AWS closed new customer access to S3 Select, effective &lt;strong&gt;July 25, 2024&lt;/strong&gt;. Existing eligible customers can continue using it. AWS also stated that it did not plan to introduce new capabilities.&lt;/p&gt;

&lt;p&gt;The distinction is eligibility to use S3 Select, rather than simply how old an AWS account is. An older account isn't automatically evidence of existing S3 Select access.&lt;/p&gt;

&lt;p&gt;My observed &lt;code&gt;MethodNotAllowed&lt;/code&gt; response is &lt;strong&gt;consistent with these availability restrictions&lt;/strong&gt;. However, AWS Support did not independently confirm the test account's eligibility, and the error alone does not establish the exact cause.&lt;/p&gt;

&lt;p&gt;That qualification matters throughout the tests below.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CSV query in Buckets — TC-S3SEL-001
&lt;/h2&gt;

&lt;p&gt;I created a CSV with six employee records and a header row. It was &lt;strong&gt;166 bytes&lt;/strong&gt;, uncompressed, and encrypted with &lt;strong&gt;SSE-S3 (&lt;code&gt;AES256&lt;/code&gt;)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The upload, metadata verification and object preview succeeded. In the query dialog, I chose CSV input, None for compression, and CSV output, then submitted the query at the start of this post.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fswzkun14z743r0ewiw3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fswzkun14z743r0ewiw3i.png" alt="CSV query configuration and the original AWS failure notification" width="590" height="408"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Detail crops from the same testing screenshot: the CSV settings and failure notification.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Buckets displayed the failure rather than query results. Being able to upload and preview the object established that those workflows worked; it did not establish that S3 Select was available.&lt;/p&gt;

&lt;p&gt;SSE-S3 also wasn't inherently an incompatible choice: the &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/API/API_SelectObjectContent.html" rel="noopener noreferrer"&gt;SelectObjectContent API documentation&lt;/a&gt; supports server-side encrypted objects, including SSE-S3.&lt;/p&gt;
&lt;h2&gt;
  
  
  Reproducing it outside Buckets
&lt;/h2&gt;

&lt;p&gt;I next used AWS CLI to separate the application interface from the underlying service operation. This is the equivalent command with generic resource names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3api &lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="nt"&gt;-object-content&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--bucket&lt;/span&gt; example-test-bucket &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--key&lt;/span&gt; data/report.csv &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--expression&lt;/span&gt; &lt;span class="s2"&gt;"SELECT * FROM S3Object s LIMIT 5"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--expression-type&lt;/span&gt; SQL &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input-serialization&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s1"&gt;'{"CSV":{"FileHeaderInfo":"USE"},"CompressionType":"NONE"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output-serialization&lt;/span&gt; &lt;span class="s1"&gt;'{"CSV":{}}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 &lt;span class="se"&gt;\&lt;/span&gt;
  /tmp/select-results.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;FileHeaderInfo: USE&lt;/code&gt; tells S3 Select to treat the first CSV line as a header. The operation and serialization options are documented in the &lt;a href="https://docs.aws.amazon.com/cli/latest/reference/s3api/select-object-content.html" rel="noopener noreferrer"&gt;AWS CLI reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My independent CLI attempt returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;An error occurred (MethodNotAllowed) when calling the
SelectObjectContent operation: The specified method is
not allowed against this resource.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F87ahm6iuwxtrlxoa19dl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F87ahm6iuwxtrlxoa19dl.png" alt="Actual AWS CLI SelectObjectContent request and MethodNotAllowed response, with identifying details covered" width="798" height="134"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The independent CLI attempt returned the same error. Private resource and profile details are covered.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This was the strongest evidence in the investigation: &lt;strong&gt;the failure was reproducible without Buckets&lt;/strong&gt;. It narrowed the investigation, while leaving the exact AWS-side reason unresolved.&lt;/p&gt;
&lt;h2&gt;
  
  
  Invalid SQL didn't produce a syntax error — TC-S3SEL-002
&lt;/h2&gt;

&lt;p&gt;The next scenario was intended to check SQL error handling. I deliberately submitted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;S3Object&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I received the same &lt;code&gt;MethodNotAllowed&lt;/code&gt; response. Correcting the expression and retrying didn't change the outcome.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdytp484lq3zwoa1ihbra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdytp484lq3zwoa1ihbra.png" alt="Deliberately invalid SQL and the unchanged failure notification" width="590" height="408"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Invalid SQL produced the same service response as the corrected query.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The editor remained responsive and let me retry. But I did &lt;strong&gt;not&lt;/strong&gt; verify how Buckets presents an actual SQL syntax error: no parser-specific response was observed. The test also cannot reveal AWS's internal order of request validation.&lt;/p&gt;
&lt;h2&gt;
  
  
  JSON reached the same boundary — TC-S3SEL-003
&lt;/h2&gt;

&lt;p&gt;I then created an uncompressed JSON Lines file with five employee records, totaling &lt;strong&gt;314 bytes&lt;/strong&gt;. Buckets identified it as JSON. With JSON input and CSV output selected, I submitted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;S3Object&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Engineering'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwj92crdvxxfq8fq3qyxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwj92crdvxxfq8fq3qyxf.png" alt="JSON input settings, department filter and original failure notification" width="590" height="408"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The JSON query also returned MethodNotAllowed; no matching records were returned.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The expression was intended to select names and departments for Engineering employees. That describes the query's intention, rather than an observed result. AWS rejected this request with the same error as the CSV request.&lt;/p&gt;
&lt;h2&gt;
  
  
  A clearer explanation in Buckets v2.8.9
&lt;/h2&gt;

&lt;p&gt;During the later JSON testing, v2.8.9 gave a more useful explanation of the service restriction. It discussed possible S3 Select availability issues and retained the original AWS error code, response and request identifiers.&lt;/p&gt;

&lt;p&gt;The explanation was careful about uncertainty: possible causes included account eligibility and unsupported resource types. The &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/API/API_SelectObjectContent.html" rel="noopener noreferrer"&gt;AWS API reference&lt;/a&gt; confirms that directory buckets and S3 on Outposts do not support this operation. Those are documented possibilities, not confirmed findings about my test environment.&lt;/p&gt;

&lt;p&gt;The expanded response is visible in the BZIP2 screenshot below, with request identifiers covered. It helped explain why repeatedly rewriting the SQL might not resolve this particular failure.&lt;/p&gt;
&lt;h2&gt;
  
  
  What the compression controls proved — TC-S3SEL-005
&lt;/h2&gt;

&lt;p&gt;Buckets offered &lt;strong&gt;None, GZIP and BZIP2&lt;/strong&gt; in its compression dropdown. I could select GZIP and BZIP2 successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpzaw0cd5u41omokmh3b9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpzaw0cd5u41omokmh3b9.png" alt="GZIP selected in the Buckets compression control" width="588" height="430"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;GZIP was selectable. Selecting an option does not compress the stored object.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I reused the existing &lt;strong&gt;uncompressed&lt;/strong&gt; JSON object and selected BZIP2. No compression-specific mismatch warning appeared before submission. When I ran the query, AWS returned &lt;code&gt;MethodNotAllowed&lt;/code&gt; again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9whk5sfuwyt72229x3ri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9whk5sfuwyt72229x3ri.png" alt="BZIP2 selected and expanded MethodNotAllowed explanation, with AWS identifiers redacted" width="510" height="508"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;BZIP2 selected for an uncompressed object. The displayed explanation concerns S3 Select availability, not a detected compression mismatch.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The dropdown worked as a UI control. &lt;strong&gt;Actual AWS decompression and compression-mismatch handling were not verified.&lt;/strong&gt; I cannot claim that Buckets detected the mismatch.&lt;/p&gt;

&lt;p&gt;AWS's &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/selecting-content-from-objects.html" rel="noopener noreferrer"&gt;format requirements&lt;/a&gt; distinguish these cases:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Supported compression&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CSV or JSON&lt;/td&gt;
&lt;td&gt;Uncompressed, GZIP or BZIP2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parquet&lt;/td&gt;
&lt;td&gt;Columnar GZIP or Snappy; no whole-object compression&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;S3 Select also has a 256 KB SQL-expression limit and a 1 MB input/result-record limit. These constraints are separate from service eligibility. Proper compression testing would need working S3 Select access and correctly compressed fixtures as well as mismatch cases.&lt;/p&gt;
&lt;h2&gt;
  
  
  Separating service behavior from application behavior
&lt;/h2&gt;

&lt;p&gt;These tests made the responsibility boundary clearer:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;AWS&lt;/th&gt;
&lt;th&gt;Buckets&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Request setup&lt;/td&gt;
&lt;td&gt;Defines the API and supported formats&lt;/td&gt;
&lt;td&gt;Collects SQL and input/output options&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Execution&lt;/td&gt;
&lt;td&gt;Evaluates the request and returns data or an error&lt;/td&gt;
&lt;td&gt;Submits the configured request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Diagnostics&lt;/td&gt;
&lt;td&gt;Returns the service code and response&lt;/td&gt;
&lt;td&gt;Displays the response and explains possible causes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The CLI reproduction supports treating this observed failure as an AWS service response rather than assuming a defect in the Buckets SQL editor. It doesn't certify every part of the application: successful execution, syntax-error presentation and compression processing still need verification in an eligible environment.&lt;/p&gt;
&lt;h2&gt;
  
  
  Amazon Athena as an alternative
&lt;/h2&gt;

&lt;p&gt;For SQL over a dataset spanning many S3 objects, &lt;a href="https://docs.aws.amazon.com/athena/latest/ug/what-is.html" rel="noopener noreferrer"&gt;Amazon Athena&lt;/a&gt; is a more suitable direction. It is a serverless analytics service that queries S3 data using SQL, with broader analytical capabilities than S3 Select's single-object API.&lt;/p&gt;

&lt;p&gt;In a common setup, the &lt;strong&gt;AWS Glue Data Catalog stores table metadata&lt;/strong&gt;: column names and types, data locations, format information and partitions. A crawler can discover that metadata, or it can be defined manually. A crawler is optional; see the &lt;a href="https://docs.aws.amazon.com/glue/latest/dg/catalog-and-crawler.html" rel="noopener noreferrer"&gt;Glue catalog documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3llao1f11pbbj7cfepih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3llao1f11pbbj7cfepih.png" alt="Athena reads source objects directly from S3, uses Glue table metadata, and stores results according to its workgroup configuration" width="800" height="536"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Illustrative architecture. Glue supplies metadata; it is not an intermediate store for the source records.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After defining a suitable employee table, the equivalent analytical query could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Engineering'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an illustrative Athena query, not something successfully executed during these S3 Select tests. Moving to Athena requires table definitions, permissions and result configuration; it isn't just changing an API name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where the results go
&lt;/h3&gt;

&lt;p&gt;With customer-managed results, Athena writes to an S3 location selected by the client or workgroup. An enforced workgroup setting takes precedence. For API calls, &lt;code&gt;StartQueryExecution.OutputLocation&lt;/code&gt; supplies the client-side location; a console setting alone does not configure API calls. See &lt;a href="https://docs.aws.amazon.com/athena/latest/ug/query-results-specify-location.html" rel="noopener noreferrer"&gt;result-location settings&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Alternatively, a workgroup can enable &lt;a href="https://docs.aws.amazon.com/athena/latest/ug/managed-results.html" rel="noopener noreferrer"&gt;Athena managed query results&lt;/a&gt;. This removes the need to supply your own results bucket. Results are retained for &lt;strong&gt;24 hours&lt;/strong&gt; at no additional managed-results storage cost, then automatically deleted. This mode does not support query-result reuse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Costs, limits and when I would process locally
&lt;/h2&gt;

&lt;p&gt;AWS currently illustrates on-demand Athena SQL pricing at &lt;strong&gt;US$5 per TB scanned&lt;/strong&gt; on its &lt;a href="https://aws.amazon.com/athena/pricing/" rel="noopener noreferrer"&gt;pricing page&lt;/a&gt;. Check the applicable Region and current rate before estimating a workload. Billing concerns data scanned, rather than just the rows returned. AWS documents rounding to the next MB and a &lt;strong&gt;10 MB minimum per query&lt;/strong&gt; in its &lt;a href="https://docs.aws.amazon.com/whitepapers/latest/big-data-analytics-options/amazon-athena.html" rel="noopener noreferrer"&gt;cost-model guidance&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Other models include SQL &lt;strong&gt;Capacity Reservations&lt;/strong&gt;, billed for compute capacity, and Apache Spark, billed for compute use. S3 storage, requests and applicable transfer charges remain relevant, including customer-managed results. Glue catalog usage can incur charges beyond its free allowance; optional crawlers and ETL jobs are billed separately under &lt;a href="https://aws.amazon.com/glue/pricing/" rel="noopener noreferrer"&gt;Glue pricing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For larger datasets, partitioning, compression and columnar formats such as Parquet can reduce scans. Workgroup scan controls can help constrain query usage.&lt;/p&gt;

&lt;p&gt;Athena still has &lt;a href="https://docs.aws.amazon.com/athena/latest/ug/service-limits.html" rel="noopener noreferrer"&gt;service quotas&lt;/a&gt;, including regional concurrency and query timeouts, and a 262,144-byte query-string limit. Its &lt;a href="https://docs.aws.amazon.com/athena/latest/ug/other-notable-limitations.html" rel="noopener noreferrer"&gt;SQL limitations&lt;/a&gt; include a 32 MB row/column size ceiling.&lt;/p&gt;

&lt;p&gt;For my 166-byte CSV or 314-byte JSON fixture, I would usually download the object and filter it with Python, pandas or DuckDB. That avoids catalog setup for a tiny one-off task, though S3 requests, transfer and local resources still matter. Athena becomes more compelling when the dataset and repeated analytical work justify that setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;No scenario produced successful S3 Select query results. The useful findings were the independent CLI reproduction, the working input controls, and the clearer explanation in v2.8.9.&lt;/p&gt;

&lt;p&gt;The lesson I will carry forward is to reproduce an unexpected service error outside the application before deciding which layer needs fixing. Here, that prevented a blocked execution test from becoming an unsupported claim about SQL or compression behavior.&lt;/p&gt;

&lt;p&gt;My next article will follow the &lt;strong&gt;Glue, Athena and S3 Tables&lt;/strong&gt; workflow: defining queryable data, running SQL, inspecting result storage and understanding the costs. Those are the next steps to test, rather than outcomes established here.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/storage/how-to-optimize-querying-your-data-in-amazon-s3/" rel="noopener noreferrer"&gt;AWS: S3 Select availability announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/selecting-content-from-objects.html" rel="noopener noreferrer"&gt;S3 Select formats and limits&lt;/a&gt; · &lt;a href="https://docs.aws.amazon.com/cli/latest/reference/s3api/select-object-content.html" rel="noopener noreferrer"&gt;CLI reference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/athena/latest/ug/" rel="noopener noreferrer"&gt;Athena User Guide&lt;/a&gt; · &lt;a href="https://aws.amazon.com/athena/pricing/" rel="noopener noreferrer"&gt;Pricing&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/glue/latest/dg/catalog-and-crawler.html" rel="noopener noreferrer"&gt;Glue Data Catalog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/athena/latest/ug/query-results-specify-location.html" rel="noopener noreferrer"&gt;Athena result locations&lt;/a&gt; · &lt;a href="https://docs.aws.amazon.com/athena/latest/ug/managed-results.html" rel="noopener noreferrer"&gt;Managed results&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>cloudcomputing</category>
      <category>sql</category>
      <category>testing</category>
    </item>
    <item>
      <title>A Deep Dive into RAG: From Basics to Better Retrieval</title>
      <dc:creator>ANSHUL VAIBHAV</dc:creator>
      <pubDate>Tue, 27 Oct 2026 03:37:33 +0000</pubDate>
      <link>https://dev.to/anshul_vaibhav_1f725e0621/a-deep-dive-into-rag-from-basics-to-better-retrieval-12e2</link>
      <guid>https://dev.to/anshul_vaibhav_1f725e0621/a-deep-dive-into-rag-from-basics-to-better-retrieval-12e2</guid>
      <description>&lt;p&gt;An LLM can explain a software feature quite well and still give you the wrong steps to use it.&lt;/p&gt;

&lt;p&gt;Consider a support chatbot answering this question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How can I recover a deleted file in version 3?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It might describe a menu from version 2, confuse the product with another application, or suggest a recovery option that does not exist. The answer can sound convincing even when the model has never seen the relevant manual.&lt;/p&gt;

&lt;p&gt;This is the problem I wanted to understand while reading &lt;em&gt;The Survey of Retrieval-Augmented Text Generation in Large Language Models&lt;/em&gt; by Yizheng Huang and Jimmy X. Huang. I used the &lt;a href="https://arxiv.org/abs/2404.10981v2" rel="noopener noreferrer"&gt;August 2024 version&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Retrieval-Augmented Generation (RAG) combines a search step with an LLM that writes the answer. The paper is a survey of existing research. What I found useful was how it breaks RAG into smaller decisions: how to prepare information, find it, select it, and use it in an answer.&lt;/p&gt;

&lt;p&gt;I'll use a hypothetical support chatbot throughout this post. It searches product manuals, troubleshooting documents, and release notes. &lt;/p&gt;

&lt;h2&gt;
  
  
  What happens without RAG?
&lt;/h2&gt;

&lt;p&gt;Without external retrieval, an LLM answers using what it learned during training and whatever information we include in the conversation.&lt;/p&gt;

&lt;p&gt;That is often enough for a general explanation. It becomes less dependable when the question needs private documentation or details from a recent release.&lt;/p&gt;

&lt;p&gt;We could paste the relevant manual into the prompt. For a small amount of information, that may be all we need. But someone still has to find the right manual and the right section. Doing that for every question becomes inconvenient as the document collection grows.&lt;/p&gt;

&lt;p&gt;RAG automates that step. The application retrieves relevant information and gives it to the model before asking it to answer.&lt;/p&gt;

&lt;p&gt;For our chatbot, the benefit is straightforward: it can consult the version 3 documentation instead of relying only on the model's learned knowledge. Updating the documents also does not require retraining the generator each time.&lt;/p&gt;

&lt;p&gt;This does not guarantee a correct answer. If retrieval finds the wrong procedure, the model can still explain the wrong procedure very clearly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The basic RAG workflow
&lt;/h2&gt;

&lt;p&gt;The survey starts with three stages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Indexing → Retrieval → Generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Indexing prepares documents for searching. A long manual is usually split into smaller passages, or &lt;em&gt;chunks&lt;/em&gt;. The application builds searchable indexes over these passages.&lt;/p&gt;

&lt;p&gt;For keyword search, the index helps locate terms. For vector search, an embedding model turns passages into numerical representations that can be compared with a question.&lt;/p&gt;

&lt;p&gt;Retrieval happens when the user asks something. The application searches for passages likely to contain the answer.&lt;/p&gt;

&lt;p&gt;Generation comes afterward. The LLM receives the question and selected passage text, then writes the response. Embeddings locate the text; the generator reads the text.&lt;/p&gt;

&lt;p&gt;Document preparation runs when documents are added or changed. It does not need to run again for every question.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1vfbr5qco87chreupj6k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1vfbr5qco87chreupj6k.png" alt="Basic RAG workflow and the survey's four-phase framework" width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2, page 3 of Huang and Huang's survey. Cropped from the paper. The upper part shows basic RAG; the lower part groups the areas where it can be improved.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How the basic workflow can be improved
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Traditional RAG&lt;/strong&gt; follows a straightforward process. Documents are split into chunks and indexed. When a question arrives, the application searches for relevant passages and sends the selected text, together with the question, to the LLM. The model then generates an answer. This basic setup often uses one retrieval pass, so its answer depends heavily on what that first search finds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enhanced RAG&lt;/strong&gt; adds ways to improve the evidence before it reaches the generator. Documents can be cleaned, summarized, or enriched with useful context before indexing. The question can be expanded or reformulated to help search. Retrieved passages can then be filtered and re-ranked. If the evidence is still insufficient, the application can refine the question and search again. Once enough supporting information is available, the LLM combines it into an answer that can be tailored to the reader.&lt;/p&gt;

&lt;p&gt;That is the broader workflow illustrated in the paper's detailed diagram below: prepare the data, refine the query, retrieve, check the results, and generate. The survey groups these ideas into &lt;strong&gt;pre-retrieval, retrieval, post-retrieval, and generation&lt;/strong&gt;. Here, “enhanced RAG” describes a set of possible improvements, not one fixed model or a requirement to use every step. For example, hybrid search can also be part of a simple pipeline.&lt;/p&gt;

&lt;p&gt;For our support chatbot, these changes address concrete problems: a chunk missing its version number, a question phrased differently from the manual, or a search that finds the recovery steps but misses a separate retention policy.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Give each chunk enough context
&lt;/h3&gt;

&lt;p&gt;A chunk containing “This option is available for 30 days” is not very useful by itself. Which option? For which product?&lt;/p&gt;

&lt;p&gt;For our chatbot, I would try keeping the section heading, recovery steps, and associated limitations together. Metadata such as the product version and document title can provide additional context.&lt;/p&gt;

&lt;p&gt;Small chunks can lose meaning; large ones can include unrelated material. The right size depends on the documents.&lt;/p&gt;

&lt;p&gt;Before changing models, I would read a few chunks and check whether they still make sense.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Make the question easier to search
&lt;/h3&gt;

&lt;p&gt;Users do not always use the terminology found in documentation. Query manipulation helps bridge that gap.&lt;/p&gt;

&lt;p&gt;The survey distinguishes three ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reformulation:&lt;/strong&gt; rewrite “get my file back in v3” as “recover a deleted file in version 3.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expansion:&lt;/strong&gt; add related terms such as “restore” or “removed document.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normalization:&lt;/strong&gt; standardize wording such as “v3” and “version 3.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rewrite must preserve the user's intent. Dropping the version number might retrieve more results while making them less useful.&lt;/p&gt;

&lt;p&gt;I would add this step when test questions reveal a wording problem, rather than assume every question needs an extra LLM call.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Use keyword and semantic search together
&lt;/h3&gt;

&lt;p&gt;BM25 ranks passages using indexed terms. It considers factors such as term frequency, how common a term is across documents, and document length. It is not whole-sentence exact matching: depending on the query settings, matching some terms can be enough to return a result. &lt;a href="https://www.elastic.co/docs/solutions/search/full-text/how-full-text-works" rel="noopener noreferrer"&gt;Elastic explains the mechanics here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dense retrieval compares learned representations of the question and passages. It can help connect “recover a removed file” with “restore a deleted document,” although it can still miss relevant evidence.&lt;/p&gt;

&lt;p&gt;Hybrid search combines these approaches. In a support application, lexical search can help with a specific error code, while semantic search can help with a user's description of the problem.&lt;/p&gt;

&lt;p&gt;The results are combined into a ranked list. Whether this improves our chatbot is something to test against a simpler baseline.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Re-rank and filter what comes back
&lt;/h3&gt;

&lt;p&gt;The first search finds candidates efficiently. A re-ranker takes a closer look at those candidates and changes their order.&lt;/p&gt;

&lt;p&gt;A cross-encoder, for example, processes a question and passage together to score their relevance. Doing this across a large collection is expensive, so it is usually applied to a smaller retrieved set. The &lt;a href="https://sbert.net/examples/sentence_transformer/applications/retrieve_rerank/README.html" rel="noopener noreferrer"&gt;Sentence Transformers documentation&lt;/a&gt; illustrates this separation.&lt;/p&gt;

&lt;p&gt;For our chatbot, re-ranking could move the actual recovery procedure above a passage that only mentions deleted files.&lt;/p&gt;

&lt;p&gt;Filtering removes unsuitable material, such as duplicate passages or instructions explicitly limited to another version. Re-ranking changes priority; filtering changes what remains.&lt;/p&gt;

&lt;p&gt;A BERT-based embedding retriever and a BERT-based cross-encoder have different jobs here. BERT itself is not a vector database or search engine.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Search again when something is missing
&lt;/h3&gt;

&lt;p&gt;Suppose the manual says recovery depends on a separate retention policy. The first search has found part of the answer, but not enough to finish it.&lt;/p&gt;

&lt;p&gt;An iterative approach can use that result to search for the policy before generating the final response. Section 4.2 of the survey discusses this along with recursive, conditional, and adaptive retrieval strategies.&lt;/p&gt;

&lt;p&gt;Extra searches need a reason and a stopping condition. Otherwise, they add delay and cost without adding evidence.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu3an13pkw4astj8jy2tb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu3an13pkw4astj8jy2tb.png" alt="Iterative RAG example with document preparation, query refinement, retrieval, filtering, re-ranking, a retrieval-quality check, and generation" width="800" height="1006"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 4, page 10 of the survey, reproduced as a crop. The paper uses a climate-change example here. Its displayed scores are illustrative.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Follow the retrieval-quality decision near the bottom left: insufficient evidence leads back to query refinement; sufficient evidence proceeds toward generation.&lt;/p&gt;

&lt;p&gt;This particular figure filters before re-ranking. That is one arrangement, not a universal order for all RAG systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Turn the evidence into a clear answer
&lt;/h3&gt;

&lt;p&gt;The survey describes &lt;em&gt;enhancing&lt;/em&gt; as combining and organizing retrieved information. Our chatbot might combine recovery steps from a manual with a limitation from the release notes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Customization&lt;/em&gt; adapts the explanation to the reader. A beginner may need numbered steps; an experienced user may prefer a short answer. The underlying facts should remain the same.&lt;/p&gt;

&lt;p&gt;If the documents do not establish a recovery method, the answer should say so rather than fill the gap with invented steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is used in current systems?
&lt;/h2&gt;

&lt;p&gt;These October 2026 documentation examples show implemented capabilities, rather than industry-wide adoption figures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hybrid retrieval and re-ranking:&lt;/strong&gt; &lt;a href="https://learn.microsoft.com/en-us/azure/search/retrieval-augmented-generation-overview?tabs=docs" rel="noopener noreferrer"&gt;Azure AI Search&lt;/a&gt; documents a classic RAG approach using hybrid search and semantic ranking. &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/rerank.html" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt; also supports reranker models with Knowledge Bases. These techniques are available as managed features, not only as research implementations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contextual retrieval:&lt;/strong&gt; &lt;a href="https://www.anthropic.com/research/contextual-retrieval" rel="noopener noreferrer"&gt;Anthropic's approach&lt;/a&gt; adds a short, chunk-specific explanation before creating embeddings and a BM25 index. For our example, that explanation could clarify which product version a passage describes. This method was published in September 2024, after the survey version used here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agentic retrieval:&lt;/strong&gt; &lt;a href="https://learn.microsoft.com/en-us/azure/search/agentic-retrieval-overview?tabs=quickstarts" rel="noopener noreferrer"&gt;Azure's documented approach&lt;/a&gt; can use an LLM to break a complex question into focused searches, run them in parallel, and combine the results. Its LLM-based query-planning capability is currently marked preview. It can help with harder questions, but adds work and latency compared with a single-query pipeline.&lt;/p&gt;

&lt;p&gt;For this support chatbot, I would start by testing good chunks, version metadata, hybrid retrieval, and re-ranking. I would add query rewriting or repeat retrieval when failures show why they are needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  How would I check whether it improved?
&lt;/h2&gt;

&lt;p&gt;The survey's evaluation discussion gives three useful questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Context relevance:&lt;/strong&gt; Did we retrieve useful evidence?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Answer relevance:&lt;/strong&gt; Did the response address the question?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faithfulness:&lt;/strong&gt; Are the answer's claims supported by the retrieved material?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Factual correctness still matters. An answer can faithfully repeat an outdated manual and be wrong for the user's situation.&lt;/p&gt;

&lt;p&gt;The main lesson I took from the survey is to inspect where the failure happened. If the right passage never reached the generator, a larger generator is not the first thing I would try.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Primary reference:&lt;/strong&gt; Yizheng Huang and Jimmy X. Huang, &lt;em&gt;The Survey of Retrieval-Augmented Text Generation in Large Language Models&lt;/em&gt;, &lt;a href="https://arxiv.org/abs/2404.10981v2" rel="noopener noreferrer"&gt;arXiv:2404.10981v2&lt;/a&gt;, 23 August 2024. Figures 2 and 4 belong to the paper's authors.&lt;/p&gt;

</description>
      <category>rag</category>
    </item>
    <item>
      <title>Working with S3 Object Tags in Buckets: SET, MERGE and CLEAR</title>
      <dc:creator>ANSHUL VAIBHAV</dc:creator>
      <pubDate>Sat, 17 Oct 2026 17:29:41 +0000</pubDate>
      <link>https://dev.to/anshul_vaibhav_1f725e0621/working-with-s3-object-tags-in-buckets-set-merge-and-clear-3dak</link>
      <guid>https://dev.to/anshul_vaibhav_1f725e0621/working-with-s3-object-tags-in-buckets-set-merge-and-clear-3dak</guid>
      <description>&lt;p&gt;A practical walkthrough for keeping Amazon S3 objects organized without changing what is inside the files.&lt;/p&gt;

&lt;p&gt;Object tags are easy to overlook when you are busy uploading and moving files around S3. But once a bucket starts filling up, a few consistent labels can make objects easier to organize and manage. The part that matters is how you update them: replacing a tag set is not the same as adding a tag to what is already there.&lt;/p&gt;

&lt;p&gt;I used Buckets by Serverless Creed to explore three useful actions—SET, MERGE and CLEAR—and checked the results in the AWS S3 console. I also compared the downloaded files with their original SHA-256 hashes to make sure the contents stayed exactly the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  A quick look at object tags
&lt;/h2&gt;

&lt;p&gt;An S3 object tag is a key-value pair attached to an object. For example, &lt;code&gt;env=test&lt;/code&gt;, &lt;code&gt;team=intern&lt;/code&gt; or &lt;code&gt;phase=review&lt;/code&gt; can describe where a file belongs or how it is used. These are separate from the file itself and from ordinary user-defined object metadata. S3 allows up to ten tags per object.&lt;/p&gt;

&lt;p&gt;Tags can be useful for organizing data and for AWS features that are configured to use them, including lifecycle rules and some access-control policies. That is why updating tags deserves a little more care than simply changing a filename.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with a small sample folder
&lt;/h2&gt;

&lt;p&gt;I worked with a handful of harmless text files in a private S3 bucket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  docs/readme.txt
  b.txt
  c.txt
  control.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The files were small enough to inspect easily. The bulk operations shown below target only &lt;code&gt;b.txt&lt;/code&gt; and &lt;code&gt;c.txt&lt;/code&gt;. I left &lt;code&gt;control.txt&lt;/code&gt; with a separate &lt;code&gt;control=keep&lt;/code&gt; tag so there was always an object to compare against the ones being updated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fabmolyt39u7il6hsbss4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fabmolyt39u7il6hsbss4.png" alt="The sample files as they appear in the Buckets object browser." width="799" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The sample files as they appear in the Buckets object browser.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  SET: replace the existing tags
&lt;/h2&gt;

&lt;p&gt;SET is the option to choose when an object needs a completely new tag set. In Buckets, select the files, open the bulk tagging action and choose &lt;strong&gt;Set (replace)&lt;/strong&gt;. For this example, I entered &lt;code&gt;team=intern&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The important word is &lt;em&gt;replace&lt;/em&gt;: tags that were on the object before, but are not included in the new set, will be removed. Before applying the change, the dialog shows the exact object keys being updated. It is worth reading that list rather than assuming every visible folder or file is included.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn1nosz9w6g668igls2oe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn1nosz9w6g668igls2oe.png" alt="SET preview in Buckets, with the new team tag and the exact object list." width="783" height="900"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;SET preview in Buckets, with the new team tag and the exact object list.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmxkbfv13du0l7s1tfv42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmxkbfv13du0l7s1tfv42.png" alt="The operation completes and Buckets displays the update result." width="784" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The operation completes and Buckets displays the update result.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Buckets reported &lt;strong&gt;Updated: 2, Failed: 0&lt;/strong&gt; for SET.&lt;/p&gt;

&lt;p&gt;I then opened the object details in AWS. The tag panel showed one tag, &lt;code&gt;team=intern&lt;/code&gt;, which is the state I expected after a replacement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqohjevhk00n70mbpbv55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqohjevhk00n70mbpbv55.png" alt="AWS S3 shows the new tag set after SET." width="800" height="213"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;AWS S3 shows the new tag set after SET.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  MERGE: add a tag without losing the others
&lt;/h2&gt;

&lt;p&gt;MERGE is more useful when the existing labels should stay. I kept &lt;code&gt;team=intern&lt;/code&gt;, switched to &lt;strong&gt;Merge&lt;/strong&gt;, and entered a new tag: &lt;code&gt;phase=review&lt;/code&gt;. I left the remove-keys field empty.&lt;/p&gt;

&lt;p&gt;That should leave both tags on the objects. If a tag key already exists, MERGE updates that key; keys not mentioned are preserved. This is usually a safer option for incremental changes than rebuilding the full tag list by hand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx1gt1nlryalujbgq0xo8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx1gt1nlryalujbgq0xo8.png" alt="MERGE adds phase=review while preserving the other tag keys." width="784" height="1011"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;MERGE adds phase=review while preserving the other tag keys.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foc14virg4qj8o739slcm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foc14virg4qj8o739slcm.png" alt="The MERGE action completes successfully." width="784" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The MERGE action completes successfully.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Buckets reported &lt;strong&gt;Updated: 2, Failed: 0&lt;/strong&gt; for MERGE.&lt;/p&gt;

&lt;p&gt;The AWS object details now displayed both &lt;code&gt;team=intern&lt;/code&gt; and &lt;code&gt;phase=review&lt;/code&gt;. Checking the entire tag list is useful here: seeing only the new key would not prove that the earlier one survived.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fznkxrtzidremsvxe95qy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fznkxrtzidremsvxe95qy.png" alt="Both team and phase are visible in the AWS object-tag panel." width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Both team and phase are visible in the AWS object-tag panel.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CLEAR: remove tags, not the object
&lt;/h2&gt;

&lt;p&gt;CLEAR does exactly what the name suggests: it removes the object’s tag set. In Buckets, choose &lt;strong&gt;Clear all&lt;/strong&gt; after selecting the intended files. The confirmation makes the scope explicit and warns that tag-dependent lifecycle rules or policies may no longer match.&lt;/p&gt;

&lt;p&gt;This is the step where I would be most careful in a real bucket. Clearing tags does not delete a file, but tags may be used by other AWS configurations. Always check the objects listed in the confirmation before proceeding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8ptxsa8fvj5xk8cryctu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8ptxsa8fvj5xk8cryctu.png" alt="CLEAR warns about removing all tags and shows the affected object keys." width="800" height="826"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;CLEAR warns about removing all tags and shows the affected object keys.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcvry36pqezxxeexn1gbm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcvry36pqezxxeexn1gbm.png" alt="Buckets confirms that the tag-removal operation completed." width="784" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Buckets confirms that the tag-removal operation completed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Buckets reported &lt;strong&gt;Updated: 2, Failed: 0&lt;/strong&gt; for CLEAR.&lt;/p&gt;

&lt;p&gt;Afterward, the AWS object details showed &lt;strong&gt;Tags (0)&lt;/strong&gt;. The AWS object details still identified &lt;code&gt;b.txt&lt;/code&gt;; the wider Buckets capture also shows &lt;code&gt;readme.txt&lt;/code&gt; remaining in the browser after tag removal. That distinction is important: removing tags is not the same thing as deleting objects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhin9voz6vf1lg8yrnfnz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhin9voz6vf1lg8yrnfnz.png" alt="The S3 tag section is empty after CLEAR." width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The S3 tag section is empty after CLEAR.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjz19mjh1zo1j5pzj5pvt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjz19mjh1zo1j5pzj5pvt.png" alt="A wider view of the Buckets object browser after tag removal." width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A wider view of the Buckets object browser after tag removal.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuou5dsfkltcz7orqkqdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuou5dsfkltcz7orqkqdk.png" alt="The AWS object details page still shows the file and its empty tag set." width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The AWS object details page still shows the file and its empty tag set.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Independent verification and SHA-256 integrity checking
&lt;/h2&gt;

&lt;p&gt;I kept &lt;code&gt;control.txt&lt;/code&gt; out of the tagging changes. Its &lt;code&gt;control=keep&lt;/code&gt; tag was still there at the end, which was a quick check that the untouched object had retained its original tag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdpwgs1oa90m2b3zaswcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdpwgs1oa90m2b3zaswcw.png" alt="The control object keeps its original tag." width="800" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The control object keeps its original tag.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For file contents, I recorded SHA-256 hashes of the original text files before uploading them. After the tagging sequence, I downloaded the S3 objects into a separate folder and compared them with that original hash list. Run the check from the download folder, with the original hash list one directory above it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shasum -a 256 -c ../original-hashes.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgt152j9kfaz411us88i7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgt152j9kfaz411us88i7.png" alt="All four downloaded files match their original SHA-256 hashes." width="602" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;All four downloaded files match their original SHA-256 hashes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The output was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs/readme.txt: OK
b.txt: OK
c.txt: OK
control.txt: OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AWS Console screenshot lists CRC64NVME as its stored checksum function. The SHA-256 verification here is a separate local comparison of the downloaded bytes against the original files.&lt;/p&gt;

&lt;p&gt;All four checks returned &lt;code&gt;OK&lt;/code&gt;. That gives two independent views of the outcome: the AWS Console shows how the tags changed, and the hash check shows that the downloaded file bytes matched the originals.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few habits worth keeping
&lt;/h2&gt;

&lt;p&gt;Three things made this workflow straightforward. First, use &lt;strong&gt;SET&lt;/strong&gt; only when replacing the full tag set is intentional; use &lt;strong&gt;MERGE&lt;/strong&gt; when existing labels should remain. Second, review the exact object list before any bulk operation, especially when folders and nested files are involved. Third, check the resulting tags in S3 rather than relying on a success message alone.&lt;/p&gt;

&lt;p&gt;For a small example like this, the difference between SET, MERGE and CLEAR is easy to see. On a busy bucket, choosing the right operation—and verifying the final state—can save a lot of confusion later.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
