Amazon S3
full text search
data search
cloud storage
information retrieval

How do you full text search an Amazon S3 bucket?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Amazon S3 is object storage, not a search engine. You can list objects by key prefix and query some structured data patterns with other AWS tools, but you cannot point a full-text query at a bucket and expect S3 itself to index document contents.

What S3 Can and Cannot Do

S3 stores objects and metadata. It can help you retrieve objects efficiently if you already know the key, prefix, or surrounding workflow. What it does not do natively is tokenize text, build inverted indexes, rank search results, or extract content from PDFs, Word documents, or HTML files.

So the real answer to "How do I full-text search an S3 bucket?" is:

  1. extract text from the objects
  2. index that text somewhere built for search
  3. query the index, not S3 directly

The Common AWS Architecture

The usual AWS design is:

  • S3 stores the original files
  • an event trigger detects new or changed objects
  • a processor extracts text and metadata
  • Amazon OpenSearch Service stores the searchable index

At a high level:

text
S3 upload -> Lambda or batch job -> text extraction -> OpenSearch index -> search API

This keeps S3 in its natural role as durable storage while a search engine handles ranking and retrieval.

Example: Index Uploaded Text Files into OpenSearch

For plain text files, a Lambda function can read the object and push it into OpenSearch. A simplified example:

python
1import boto3
2import json
3import urllib.parse
4from opensearchpy import OpenSearch
5
6s3 = boto3.client("s3")
7client = OpenSearch(
8    hosts=[{"host": "search-example.us-east-1.es.amazonaws.com", "port": 443}],
9    use_ssl=True,
10    verify_certs=True,
11)
12
13def lambda_handler(event, context):
14    record = event["Records"][0]
15    bucket = record["s3"]["bucket"]["name"]
16    key = urllib.parse.unquote_plus(record["s3"]["object"]["key"])
17
18    response = s3.get_object(Bucket=bucket, Key=key)
19    text = response["Body"].read().decode("utf-8")
20
21    document = {
22        "bucket": bucket,
23        "key": key,
24        "content": text,
25    }
26
27    client.index(index="s3-documents", id=key, body=document)
28
29    return {"statusCode": 200, "body": json.dumps("indexed")}

This is enough for text files. For PDFs or Office documents, add a text-extraction step before indexing.

What to Use for Non-Text Documents

Many S3 buckets store binary documents rather than raw text. In those cases, you need content extraction first. Common approaches include:

  • AWS Lambda with a library that parses PDFs or Office formats
  • AWS Textract for scanned or image-heavy documents
  • a containerized batch job for large or complex documents

Once text is extracted, index the result along with useful metadata such as object key, upload time, tags, customer ID, or document type.

What About Athena or S3 Select?

These tools are useful, but they are not substitutes for full-text search.

  • Amazon Athena is good for SQL over structured data stored in S3, such as JSON, CSV, or Parquet.
  • S3 Select can retrieve subsets of structured object content.

Neither one is a general relevance-ranked document search engine. If your data is logs, tables, or newline-delimited JSON, Athena may be enough. If your requirement is "search all words inside uploaded documents," use an index built for that purpose.

A Search Query Example

Once data is in OpenSearch, querying becomes straightforward:

python
1query = {
2    "query": {
3        "match": {
4            "content": "customer refund policy"
5        }
6    }
7}
8
9results = client.search(index="s3-documents", body=query)
10for hit in results["hits"]["hits"]:
11    print(hit["_source"]["key"])

Now the search is running against indexed document content, not against S3 object storage.

Operational Considerations

A production design usually needs more than raw indexing:

  • re-index documents when objects are replaced
  • delete index entries when S3 objects are deleted
  • store ACL-related metadata if access control matters
  • normalize text, language, and file encodings
  • monitor indexing failures and dead-letter events

For large buckets, a one-time backfill job is also necessary so the index covers existing objects, not just new uploads.

Common Pitfalls

  • Expecting S3 itself to support keyword search inside documents leads to the wrong architecture.
  • Indexing only filenames or object keys is not full-text search.
  • Ignoring document parsing means PDFs and Office files appear "missing" from search results.
  • Using Athena for relevance-ranked text search usually results in a poor experience.
  • Forgetting delete and update handling causes the search index to drift away from the bucket contents.

Summary

  • S3 does not provide native full-text search over object contents.
  • The standard solution is S3 for storage plus text extraction plus an index such as OpenSearch.
  • Lambda works well for event-driven indexing of new uploads.
  • Athena and S3 Select help with structured queries, not general document search.
  • Build the search system around an external index, and treat S3 as the source of truth for the files.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.