Hard๐Ÿ‘ค 8-15 years 5 min read Updated Aug 24, 2026

DynamoDB Single Table Design โ€” Interview Guide

Reviewed by Gurusankar M. ยท Updated Aug 24, 2026

Asked inAmazonGoogleMicrosoft
#dynamodb#single-table design#access patterns#partition key#sort key#gsi#nosql modeling
Report issue

โšก Short Answer

Single-table design stores multiple entity types in ONE table, using composite keys (PK/SK) and GSIs crafted so each known access pattern is served by a single efficient query โ€” no joins, no multiple round-trips. It trades modeling complexity and rigidity for low latency and cost at scale.

โ˜•Coffee Chat Question

Concept Made Simple

โ€œWhat is DynamoDB single-table design, and why do experts use it?โ€

๐Ÿง Mind Map Answer

Remember It Faster

One tableโ†’many entity types together
Composite keysโ†’PK/SK model relationships
GSIsโ†’serve additional access patterns
Goalโ†’one query per access pattern, no joins
PKSKItem
CUSTOMER#123METADATACustomer profile
CUSTOMER#123ORDER#001Order 1, belongs to this customer
CUSTOMER#123ORDER#002Order 2, belongs to this customer
ORDER#001METADATAOrder details, fetched directly by order id

One table, two access patterns, no join: Query PK = CUSTOMER#123 returns the customer's profile and every one of their orders in a single request (they share the same partition). Query PK = ORDER#001 fetches that order's own details directly. The keys are modeled around the *known* access patterns โ€” not around normalized entities the way a relational schema would be.

Overloaded GSIs are what make one table serve many entity types cleanly. Instead of a dedicated index per entity, a single GSI1PK/GSI1SK pair holds different, purpose-built values per item type โ€” for a CUSTOMER item, GSI1PK might be EMAIL#<email> (to look customers up by email); for an ORDER item, the same attribute name might hold STATUS#<status> (to list orders by status). The GSI attribute name is reused ("overloaded"), but each entity type puts a differently-shaped value in it โ€” so one physical index quietly serves several unrelated access patterns instead of one GSI per query.

Adding a genuinely new access pattern later has three levels of cost, in order of preference. Cheapest: if an existing GSI's key already happens to sort/filter the new way you need, you're done โ€” no schema change at all. Next: add a new GSI (GSI2PK/GSI2SK) โ€” DynamoDB backfills it automatically from existing items, no downtime, but every existing item needs the new attribute populated, which for old items means either the application computed it defensively when the item was first written (the standard single-table-design discipline: populate GSI attributes for patterns you might need, not just ones you use today) or a one-time backfill script that scans and updates every item. Most expensive: the new pattern needs a key shape the existing attributes can't produce at all โ€” that usually means a genuinely new item type or a denormalized copy, which is the scenario the whatIf above calls a "painful migration," and exactly why enumerating access patterns up front matters so much more here than in a relational schema.

Sparse GSIs turn "only some items have this attribute" into a free filtered index. A GSI only indexes items that actually have a value for the GSI's key attribute โ€” an item missing that attribute simply doesn't appear in the index at all, rather than appearing with a null key. That's a deliberate feature, not an edge case to work around: give the GSI key attribute a value only on ORDER items where status = PENDING, and the GSI now contains only pending orders โ€” no filter expression needed, no scanning past shipped/delivered orders to find them, because they were never written into the index in the first place. It's the standard single-table-design technique for "give me only the items matching some condition" queries, and it's a favorite follow-up precisely because it looks like a quirky side effect until you see it used deliberately. Because populating the key is what includes an item, removing it from a sparse index is just as deliberate โ€” clear the GSI key attribute (e.g. when an order ships) and the item vanishes from the index on the very next write, no separate cleanup step required.

โŒจ๏ธHands-on Keyboard

Learn by Doing

java
// Overloaded GSI: GSI1PK holds different value shapes per entity type,
// so one index serves two unrelated access patterns.
// Item shapes written earlier:
//   CUSTOMER#123 -> GSI1PK = "EMAIL#alice@example.com", GSI1SK = "CUSTOMER#123"
//   ORDER#001    -> GSI1PK = "STATUS#SHIPPED",           GSI1SK = "ORDER#001"

// Pattern A: look up a customer by email โ€” no scan, no separate email-index table
QueryRequest byEmail = QueryRequest.builder()
    .tableName("AppTable")
    .indexName("GSI1")
    .keyConditionExpression("GSI1PK = :pk")
    .expressionAttributeValues(Map.of(
        ":pk", AttributeValue.fromS("EMAIL#alice@example.com")))
    .build();

// Pattern B: list every order currently SHIPPED โ€” same index, different key shape
QueryRequest byStatus = QueryRequest.builder()
    .tableName("AppTable")
    .indexName("GSI1")
    .keyConditionExpression("GSI1PK = :pk")
    .expressionAttributeValues(Map.of(
        ":pk", AttributeValue.fromS("STATUS#SHIPPED")))
    .build();
Output
Two unrelated access patterns (email lookup, status listing) served by one GSI.

๐Ÿ”ฅWhat If?

Think Beyond the Expected

Why is single-table design controversial / risky?

You must know ALL access patterns up front โ€” the key/GSI design is baked around them. New, unforeseen query needs can require painful migrations or extra GSIs, and the schema is hard for newcomers to read. It maximizes performance/cost but sacrifices flexibility, so it's not always the right call.

๐Ÿ˜‚Real World

AWS/Alex DeBrie advocate single-table design for high-scale DynamoDB apps to hit single-digit-ms latency and minimize cost; teams with evolving requirements often prefer simpler multi-table or a relational DB. Overloaded GSIs are usually the detail that trips up engineers new to the pattern โ€” the index looks like it holds one kind of data until you notice the key values are deliberately shaped differently per entity type.

๐ŸŽฏInterviewer's Expectation

Keywords they're listening for:

โœ“ multiple entities in one tableโœ“ composite PK/SK + GSIsโœ“ one query per access patternโœ“ must know patterns upfrontโœ“ flexibility trade-off

โš ๏ธCommon Mistakes

  • โœ—Single-table design with unknown/evolving patterns
  • โœ—Relational thinking (joins) on DynamoDB
  • โœ—Not planning GSIs for all patterns

โœ…Best Practices

  • โœ“Enumerate all access patterns first
  • โœ“Model keys/GSIs per pattern
  • โœ“Prefer simpler designs when flexibility matters

๐Ÿ”Follow-up Questions

  • 1How do overloaded GSIs work?
  • 2When would you NOT use single-table design?
  • 3How do you add a new access pattern later?

๐ŸงฉRelated Technologies

DynamoDBGSI/LSIcomposite keys

๐Ÿ“šReferences

Continue Learning with AI

Take this question deeper with your favourite AI assistant. Pick a depth, copy the prompt, or open it directly โ€” AI is your learning companion, not a shortcut.

Plain-language foundations

I'm preparing for a software engineering interview and want to understand this from scratch, as a beginner.

Topic: DynamoDB (AWS)
Interview question: "What is DynamoDB single-table design, and why do experts use it?"

Please:
1. Explain the core idea in simple, plain language, using an everyday analogy.
2. Define any technical terms you use.
3. Walk through one small, concrete example.
4. Finish with a single sentence I can easily remember.

Keep the tone friendly and assume I'm new to this topic.

Was this answer helpful?

Support our platform by exploring our recommended products.

As an Amazon affiliate, purchases through these links may earn us a small commission โ€” at no extra cost to you. It helps keep Full Stack Interview Guru free.

Related Questions