Data Length Contraction

Reduce storage costs and throughput consumption by shortening attribute names in high-volume tables.

What is data length contraction?

Amazon DynamoDB is a schema-less database, where the total size of an item is the sum of the lengths of its attribute names and values.1 Reducing the data length of attribute names can significantly reduce storage costs and lower provisioned throughput requirements.

Key concept: DynamoDB charges you for the entire item size, including:

  • Attribute names (the keys)
  • Attribute values (the data)
  • Data type descriptors

This means verbose attribute names directly increase your costs, especially at scale.

When to use data length contraction

High-impact scenarios:

  • High-volume tables - Millions or billions of items where savings multiply
  • Wide tables - Many attributes per item (>10 attributes)
  • Frequently updated items - Write-heavy workloads where WCU costs are significant
  • Hot data - Frequently read data where RCU costs matter
  • Cost-sensitive applications - Where every optimization counts

Low-impact scenarios:

  • Small tables (<1M items) where savings are minimal
  • Tables with few attributes (<5 attributes)
  • Rarely accessed cold data where throughput costs are already low

Implementation strategies

Strategy 1: Abbreviate common words

Replace common long words with standard abbreviations:

Before:

{
  "product_identifier": "prod-12345",
  "product_description": "Wireless mouse",
  "manufacturer_name": "TechCorp",
  "inventory_quantity": 150,
  "last_updated_timestamp": "2025-11-22T10:00:00Z",
  "price_in_cents": 2999,
  "is_available_for_purchase": true
}

After:

{
  "prod_id": "prod-12345",
  "desc": "Wireless mouse",
  "mfr": "TechCorp",
  "qty": 150,
  "updated": "2025-11-22T10:00:00Z",
  "price": 2999,
  "avail": true
}

Savings: 88 bytes per item → 41 bytes = 47 bytes saved (53% reduction)

Strategy 2: Single-letter keys for nested objects

For nested objects with predictable structure, use single letters:

Before:

{
  "user_id": "user-123",
  "shipping_address": {
    "street_address": "123 Main St",
    "city_name": "Seattle",
    "state_code": "WA",
    "postal_code": "98101"
  },
  "billing_address": {
    "street_address": "456 Oak Ave",
    "city_name": "Portland",
    "state_code": "OR",
    "postal_code": "97201"
  }
}

After:

{
  "uid": "user-123",
  "ship": {
    "st": "123 Main St",
    "c": "Seattle",
    "s": "WA",
    "z": "98101"
  },
  "bill": {
    "st": "456 Oak Ave",
    "c": "Portland",
    "s": "OR",
    "z": "97201"
  }
}

Savings: 159 bytes → 87 bytes = 72 bytes saved (45% reduction)

Strategy 3: Eliminate redundant prefixes

Remove table-specific prefixes that are implied by context:

Before:

{
  "order_id": "order-789",
  "order_date": "2025-11-22",
  "order_total": 99.99,
  "order_status": "shipped",
  "order_items": [...]
}

After:

{
  "id": "order-789",
  "date": "2025-11-22",
  "total": 99.99,
  "status": "shipped",
  "items": [...]
}

Savings: 54 bytes → 30 bytes = 24 bytes saved (44% reduction)

Best practices

Maintain a mapping document

Create and maintain a clear mapping between shortened and full attribute names:

// attribute-mapping.js
const ATTRIBUTE_MAPPING = {
  // User attributes
  'uid': 'user_id',
  'email': 'email_address',
  'fname': 'first_name',
  'lname': 'last_name',
  'created': 'created_timestamp',
  
  // Product attributes
  'prod_id': 'product_identifier',
  'desc': 'product_description',
  'mfr': 'manufacturer_name',
  'qty': 'inventory_quantity',
  'price': 'price_in_cents',
  
  // Order attributes
  'oid': 'order_id',
  'uid': 'user_id',
  'total': 'order_total_cents',
  'status': 'order_status',
  'ship': 'shipping_address',
  'bill': 'billing_address'
};

// Helper function to expand abbreviations for readability
function expandAttributes(item) {
  const expanded = {};
  for (const [key, value] of Object.entries(item)) {
    const fullKey = ATTRIBUTE_MAPPING[key] || key;
    expanded[fullKey] = value;
  }
  return expanded;
}

Use abstraction layers

Create data access layers that handle the translation:

# data_access_layer.py
class DynamoDBMapper:
    """Abstract DynamoDB access with attribute name translation."""
    
    COMPACT_TO_VERBOSE = {
        'uid': 'user_id',
        'email': 'email_address',
        'fname': 'first_name',
        'lname': 'last_name',
        'created': 'created_timestamp'
    }
    
    VERBOSE_TO_COMPACT = {v: k for k, v in COMPACT_TO_VERBOSE.items()}
    
    @classmethod
    def to_dynamodb(cls, verbose_item):
        """Convert verbose attribute names to compact for storage."""
        return {
            cls.VERBOSE_TO_COMPACT.get(k, k): v 
            for k, v in verbose_item.items()
        }
    
    @classmethod
    def from_dynamodb(cls, compact_item):
        """Convert compact attribute names to verbose for application use."""
        return {
            cls.COMPACT_TO_VERBOSE.get(k, k): v 
            for k, v in compact_item.items()
        }

# Usage
user_data = {
    'user_id': 'user-123',
    'email_address': 'user@example.com',
    'first_name': 'John',
    'last_name': 'Doe',
    'created_timestamp': '2025-11-22T10:00:00Z'
}

# Store in DynamoDB with compact names
compact_data = DynamoDBMapper.to_dynamodb(user_data)
table.put_item(Item=compact_data)
# Stored as: {'uid': 'user-123', 'email': 'user@example.com', ...}

# Retrieve and expand for application use
response = table.get_item(Key={'uid': 'user-123'})
verbose_data = DynamoDBMapper.from_dynamodb(response['Item'])
# Returns: {'user_id': 'user-123', 'email_address': 'user@example.com', ...}

Balance readability and optimization

Good abbreviations:

  • Industry-standard abbreviations (qty, desc, addr)
  • Single-letter codes for well-known fields (c for city, s for state)
  • Shortened forms that retain meaning (prod, mfr, inv)

Avoid:

  • Ambiguous single letters without context (a, b, x, y)
  • Inconsistent abbreviation patterns
  • Cryptic codes that require constant reference

Document your conventions

Include attribute mapping in your codebase documentation:

User Table (users)

CompactFull NameDescription
uiduser_idUnique user identifier
emailemail_addressUser email address
fnamefirst_nameUser first name
lnamelast_nameUser last name
createdcreated_timestampAccount creation timestamp
statusaccount_statusAccount status (active/suspended/deleted)

Trade-offs to consider

Advantages

  • Direct cost savings - Reduced storage and throughput costs
  • Performance benefits - Smaller items transfer faster over the network
  • Capacity efficiency - More items processed per capacity unit
  • Compounding savings - Benefits multiply with table size

Disadvantages

  • Reduced readability - Compact names are less self-documenting

  • Increased complexity - Requires mapping layer and documentation

  • Team onboarding - New developers need to learn attribute mappings

  • Debugging difficulty - Less obvious what data represents when viewing raw items

  • Migration effort - Existing tables require careful migration planning

  • DynamoDB Item Sizes and Formats

  • Best Practices for DynamoDB

  • DynamoDB Naming Rules

Footnotes

  1. DynamoDB item sizes and formats