DynamoDB

Overview

Create two DynamoDB tables to store Lambda function results:

TableUsed ByPurpose
bandup-evaluationsWriting + Speaking EvaluatorsStores IELTS band scores, feedback, transcripts
bandup-flashcard-setsFlashcard GeneratorStores generated flashcards and document metadata

Table 1: Evaluations Table

Stores results from both Writing Evaluator and Speaking Evaluator Lambda functions.

SettingValue
Table namebandup-evaluations
Partition keyevaluation_id (String)
Sort keyuser_id (String)
Billing modeOn-demand (PAY_PER_REQUEST)

Table Schema:

AttributeTypeDescription
evaluation_idStringUnique session ID (PK)
user_idStringUser identifier (SK)
evaluation_typeStringwriting or speaking
statusStringprocessing, completed, failed
overall_bandStringOverall IELTS band score (e.g., “7.0”)
task_achievement_bandStringWriting only
coherence_bandStringWriting only
lexical_bandStringBoth Writing and Speaking
grammar_bandStringBoth Writing and Speaking
fluency_bandStringSpeaking only
pronunciation_bandStringSpeaking only
transcriptStringSpeaking only - transcribed audio
feedbackStringJSON-encoded detailed feedback
model_usedStringAI model used for evaluation
created_atNumberUnix timestamp

Example Item (Writing):

{
  "evaluation_id": "eval-abc123",
  "user_id": "user-456",
  "evaluation_type": "writing",
  "status": "completed",
  "overall_band": "7.0",
  "task_achievement_band": "7.0",
  "coherence_band": "6.5",
  "lexical_band": "7.0",
  "grammar_band": "6.5",
  "feedback": "{\"strengths\":[...],\"weaknesses\":[...]}",
  "model_used": "gemini-writing_task2",
  "created_at": 1733644800
}

Example Item (Speaking):

{
  "evaluation_id": "speak-xyz789",
  "user_id": "user-456",
  "evaluation_type": "speaking",
  "status": "completed",
  "overall_band": "7.0",
  "fluency_band": "7.0",
  "lexical_band": "6.5",
  "grammar_band": "7.0",
  "pronunciation_band": "6.5",
  "transcript": "Well, I'd like to talk about...",
  "duration": "120.5",
  "word_count": 185,
  "feedback": "{\"fluency\":{...},\"pronunciation\":{...}}",
  "model_used": "gemini-2.5-flash-audio",
  "created_at": 1733644800
}

Table 2: Flashcard Sets Table

Stores results from Flashcard Generator Lambda function.

SettingValue
Table namebandup-flashcard-sets
Partition keyset_id (String)
Sort keyuser_id (String)
Billing modeOn-demand (PAY_PER_REQUEST)

Table Schema:

AttributeTypeDescription
set_idStringUnique flashcard set ID (PK)
user_idStringUser identifier (SK)
document_idStringSource document S3 key
statusStringprocessing, completed, failed
flashcardsStringJSON-encoded array of flashcards
total_cardsNumberNumber of flashcards generated
page_countNumberNumber of pages in source PDF
chunk_countNumberNumber of text chunks indexed
created_atNumberUnix timestamp

Example Item:

{
  "set_id": "flashcard-set-123",
  "user_id": "user-456",
  "document_id": "uploads/documents/user-456/vocab-guide.pdf",
  "status": "completed",
  "flashcards": "[{\"question\":\"What is...\",\"answer\":\"...\"}]",
  "total_cards": 15,
  "page_count": 8,
  "chunk_count": 24,
  "created_at": 1733644800
}

Create Tables with AWS CLI

# Create evaluations table (Writing + Speaking)
aws dynamodb create-table \
    --table-name bandup-evaluations \
    --attribute-definitions \
        AttributeName=evaluation_id,AttributeType=S \
        AttributeName=user_id,AttributeType=S \
    --key-schema \
        AttributeName=evaluation_id,KeyType=HASH \
        AttributeName=user_id,KeyType=RANGE \
    --billing-mode PAY_PER_REQUEST \
    --tags Key=Project,Value=bandup Key=Environment,Value=production

# Create flashcard sets table
aws dynamodb create-table \
    --table-name bandup-flashcard-sets \
    --attribute-definitions \
        AttributeName=set_id,AttributeType=S \
        AttributeName=user_id,AttributeType=S \
    --key-schema \
        AttributeName=set_id,KeyType=HASH \
        AttributeName=user_id,KeyType=RANGE \
    --billing-mode PAY_PER_REQUEST \
    --tags Key=Project,Value=bandup Key=Environment,Value=production

Enable Point-in-Time Recovery

Enable PITR for data protection:

# Enable PITR for evaluations table
aws dynamodb update-continuous-backups \
    --table-name bandup-evaluations \
    --point-in-time-recovery-specification PointInTimeRecoveryEnabled=true

# Enable PITR for flashcard sets table
aws dynamodb update-continuous-backups \
    --table-name bandup-flashcard-sets \
    --point-in-time-recovery-specification PointInTimeRecoveryEnabled=true

Query Patterns

Get user’s evaluation history:

response = table.query(
    IndexName='user_id-created_at-index',  # If GSI exists
    KeyConditionExpression=Key('user_id').eq('user-456'),
    ScanIndexForward=False,  # Most recent first
    Limit=10
)

Get specific evaluation by ID:

response = table.get_item(
    Key={
        'evaluation_id': 'eval-abc123',
        'user_id': 'user-456'
    }
)

Get user’s flashcard sets:

response = table.query(
    KeyConditionExpression=Key('user_id').eq('user-456'),
    FilterExpression=Attr('status').eq('completed')
)

Lambda Environment Variables

Configure Lambda functions to use these tables:

Lambda FunctionEnvironment VariableValue
Writing EvaluatorDYNAMODB_EVALUATIONSbandup-evaluations
Speaking EvaluatorDYNAMODB_EVALUATIONSbandup-evaluations
Flashcard GeneratorDYNAMODB_FLASHCARD_SETSbandup-flashcard-sets

IAM Policy for Lambda Access

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DynamoDBAccess",
      "Effect": "Allow",
      "Action": [
        "dynamodb:PutItem",
        "dynamodb:GetItem",
        "dynamodb:UpdateItem",
        "dynamodb:Query"
      ],
      "Resource": [
        "arn:aws:dynamodb:${AWS_REGION}:${AWS_ACCOUNT_ID}:table/bandup-evaluations",
        "arn:aws:dynamodb:${AWS_REGION}:${AWS_ACCOUNT_ID}:table/bandup-flashcard-sets"
      ]
    }
  ]
}

Next Steps

Proceed to Bedrock Integration to configure Amazon Titan Embeddings.