DynamoDB for Scalable Data Storage: Managing User Progress in a Fitness App
Managing and scaling dynamic user data, such as progress logs and exercise details, is crucial in fitness-tracking applications. Amazon DynamoDB, with its serverless architecture and high throughput, is a perfect match for this requirement. It supports low-latency reads and writes, handles high concurrency, and allows schema flexibility.
This article delves into the specific DynamoDB setup in your fitness app, leveraging configurations directly from your project files. It explains the schema design, integration with Lambda for data processing and handling of high-concurrency use cases.
Why DynamoDB Is Ideal for Fitness Apps
Fitness apps generate diverse, dynamic datasets, such as:
DynamoDB offers:
DynamoDB Table Schema for Fitness Tracking
Your project uses two tables, each tailored to specific fitness app data:
1. Raw Data Table
This table stores detailed workout logs for each user with the following attributes:
Primary Key:
Global Secondary Index:
2. Aggregated Data Table
This table stores summary metrics for user progress:
Primary Key:
Terraform Configuration for DynamoDB
Below is the actual configuration from your project:
Recommended by LinkedIn
resource "aws_dynamodb_table" "raw_data" {
name = "${var.environment}_raw_data"
billing_mode = "PAY_PER_REQUEST"
attribute {
name = "user"
type = "S"
}
attribute {
name = "date"
type = "S"
}
attribute {
name = "exercise"
type = "S"
}
hash_key = "user"
range_key = "date"
global_secondary_index {
name = "exercise-date-index"
hash_key = "exercise"
range_key = "date"
projection_type = "ALL"
}
stream_enabled = true
stream_view_type = "NEW_AND_OLD_IMAGES"
tags = var.tags
}
resource "aws_dynamodb_table" "aggregates" {
name = "${var.environment}_aggregated"
billing_mode = "PAY_PER_REQUEST"
attribute {
name = "user"
type = "S"
}
attribute {
name = "exercise_name"
type = "S"
}
hash_key = "user"
range_key = "exercise_name"
tags = var.tags
}
Lambda Integration for Data Processing
Updating User Progress
The following Lambda function demonstrates how to record detailed workout data in the raw_data table:
import json
import boto3
def handler(event, context):
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('raw_data')
body = json.loads(event['body'])
user = body['user']
date = body['date']
exercise = body['exercise']
details = body['details']
# Save the data
table.put_item(
Item={
'user': user,
'date': date,
'exercise': exercise,
'details': details
}
)
return {
'statusCode': 200,
'body': json.dumps({'message': 'Workout logged successfully!'})
}
Querying Aggregated Data
This Lambda function retrieves summary metrics from the aggregates table:
def handler(event, context):
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('aggregates')
user = event['queryStringParameters']['user']
response = table.query(
KeyConditionExpression="user = :user",
ExpressionAttributeValues={":user": user}
)
return {
'statusCode': 200,
'body': json.dumps(response['Items'])
}
Handling High Concurrency
Strategies for Scalability
Visuals
DynamoDB Console
Example Query Results
Example output from a query in the AWS console:
"user","date","exercise","exercise_reps","exercise_volumes","raw_exercises","total_volume"
"todd@bernsonfamily.com","2025-01-14","DAILY_SUMMARY","{""situps"":{""N"":""150""},""deadlift"":{""N"":""90""},""muscleups"":{""N"":""487""},""pullups"":{""N"":""60""}}","{""situps"":{""N"":""20250""},""deadlift"":{""N"":""13950""},""muscleups"":{""N"":""7305""},""pullups"":{""N"":""12120""}}","[{""M"":{""name"":{""S"":""deadlift""},""weight"":{""N"":""155""},""reps"":{""N"":""90""}}},{""M"":{""name"":{""S"":""muscleups""},""weight"":{""N"":""15""},""reps"":{""N"":""487""}}},{""M"":{""name"":{""S"":""pullups""},""weight"":{""N"":""202""},""reps"":{""N"":""60""}}},{""M"":{""name"":{""S"":""situps""},""weight"":{""N"":""135""},""reps"":{""N"":""150""}}}]","53625"
Amazon DynamoDB forms the backbone of the data storage layer for your fitness tracking app. By using the schema and Terraform configurations you’ve provided, this architecture supports low-latency, scalable operations, enabling seamless user experiences even under high concurrency. With additional features like DynamoDB Streams and GSIs, your setup is both robust and future-proof.