Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/azfar-imtiaz/PayPulse-Cloud/llms.txt

Use this file to discover all available pages before exploring further.

PayPulse Cloud uses 11 DynamoDB tables defined in aws-infra-terraform/dynamodb.tf. All tables have server-side encryption enabled.

Rental invoices

RentalInvoices

Stores parsed rental invoice data. This is the primary table for the rental invoice feature.
resource "aws_dynamodb_table" "rental_invoices" {
  name           = "RentalInvoices"
  billing_mode   = "PROVISIONED"
  read_capacity  = 5
  write_capacity = 5

  hash_key  = "UserID"
  range_key = "InvoiceID"

  global_secondary_index {
    name            = "due_date_year-due_date_month-index"
    hash_key        = "due_date_year"
    range_key       = "due_date_month"
    projection_type = "ALL"
    read_capacity   = 1
    write_capacity  = 1
  }

  stream_enabled   = true
  stream_view_type = "NEW_AND_OLD_IMAGES"

  server_side_encryption {
    enabled = true
  }
}
PropertyValue
Billing modePROVISIONED (5 RCU / 5 WCU base)
Partition keyUserID (String)
Sort keyInvoiceID (String)
GSIdue_date_year-due_date_month-index (hash: due_date_year, range: due_date_month)
StreamNEW_AND_OLD_IMAGES
EncryptionServer-side (AES-256)
The DynamoDB stream on this table triggers the send_invoice_notification Lambda whenever a new invoice record is inserted. Autoscaling is configured separately — see Autoscaling below.

Users

Users

Stores user account information and Gmail connection state.
resource "aws_dynamodb_table" "users" {
  name         = "Users"
  billing_mode = "PAY_PER_REQUEST"

  hash_key = "UserID"

  global_secondary_index {
    hash_key        = "Email"
    name            = "Email-index"
    projection_type = "ALL"
  }

  tags = {
    Environment = "production"
  }
}
PropertyValue
Billing modePAY_PER_REQUEST
Partition keyUserID (String)
GSIEmail-index (hash: Email)
The Email-index GSI supports login lookups by email address without a full table scan. The table also stores a last_retail_invoice_fetch timestamp used for incremental retail invoice fetching.

Retail invoices

RetailInvoices

Base table for retail invoices. Contains summary metadata for every retail invoice across all categories.
resource "aws_dynamodb_table" "retail_invoices" {
  name         = "RetailInvoices"
  billing_mode = "PAY_PER_REQUEST"

  hash_key  = "UserID"
  range_key = "InvoiceID"

  # GSI-1: date-based queries per user
  global_secondary_index {
    name            = "invoice_date-index"
    hash_key        = "UserID"
    range_key       = "invoice_date"
    projection_type = "ALL"
  }

  # GSI-2: category + date queries
  global_secondary_index {
    name            = "sub_type-invoice_date-index"
    hash_key        = "UserID_SubType"
    range_key       = "invoice_date"
    projection_type = "ALL"
  }

  stream_enabled   = true
  stream_view_type = "NEW_AND_OLD_IMAGES"

  point_in_time_recovery {
    enabled = true
  }

  server_side_encryption {
    enabled = true
  }
}
PropertyValue
Billing modePAY_PER_REQUEST
Partition keyUserID (String)
Sort keyInvoiceID (String)
GSI-1invoice_date-index (hash: UserID, range: invoice_date)
GSI-2sub_type-invoice_date-index (hash: UserID_SubType, range: invoice_date)
StreamNEW_AND_OLD_IMAGES
Point-in-time recoveryEnabled
EncryptionServer-side (AES-256)
GSI-2 uses a composite key UserID_SubType (e.g., user_abc123_food-delivery) to efficiently retrieve all invoices for a user within a specific category. Attributes stored per item include: vendor_name, sub_type, total_amount, currency, invoice_date, s3_path.

Retail detail tables

Each retail category has a dedicated detail table keyed by InvoiceID. These hold category-specific line-item data parsed from the invoice HTML.
Table nameVariable default
FoodDeliveryInvoicesfood_delivery_invoices_table
ClothingInvoicesclothing_invoices_table
TechnologyInvoicestechnology_invoices_table
SubscriptionInvoicessubscription_invoices_table
GroceryInvoicesgrocery_invoices_table
MiscellaneousUtilityInvoicesmisc_utility_invoices_table
MiscellaneousInvoicesmisc_invoices_table
TravelInvoicestravel_invoices_table
All eight tables share the same schema:
resource "aws_dynamodb_table" "food_delivery_invoices" {
  name         = "FoodDeliveryInvoices"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "InvoiceID"

  attribute {
    name = "InvoiceID"
    type = "S"
  }

  server_side_encryption {
    enabled = true
  }

  tags = {
    Environment = "production"
  }
}
PropertyValue
Billing modePAY_PER_REQUEST
Partition keyInvoiceID (String)
EncryptionServer-side (AES-256)

Vendor configuration

VendorConfig

Drives automated retail invoice fetching. Each item represents one vendor with email patterns, subject keywords, and parser configuration.
resource "aws_dynamodb_table" "vendor_config" {
  name         = "VendorConfig"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "vendor_id"

  server_side_encryption {
    enabled = true
  }
}
PropertyValue
Billing modePAY_PER_REQUEST
Partition keyvendor_id (String)
EncryptionServer-side (AES-256)
Attributes per item include: vendor_name, invoice_sub_type, email_patterns, subject_keywords, parser_type, and an active status flag. Adding a new vendor to this table enables invoice fetching for that vendor without any code changes.

Autoscaling

Read and write autoscaling is configured for the RentalInvoices table in dynamodb_autoscaling.tf.
resource "aws_appautoscaling_target" "dynamodb_read_target" {
  min_capacity       = 1
  max_capacity       = 10
  resource_id        = "table/RentalInvoices"
  scalable_dimension = "dynamodb:table:ReadCapacityUnits"
  service_namespace  = "dynamodb"
}

resource "aws_appautoscaling_policy" "dynamodb_read_policy" {
  name        = "DynamoDBReadAutoScalingPolicy"
  policy_type = "TargetTrackingScaling"

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = "DynamoDBReadCapacityUtilization"
    }
    target_value       = 70.0
    scale_in_cooldown  = 60
    scale_out_cooldown = 60
  }
}
SettingValue
Min capacity1 unit
Max capacity10 units
Target utilization70%
Scale-in cooldown60 seconds
Scale-out cooldown60 seconds
Both read and write capacity are scaled independently using the same target utilization (70%). All other tables use PAY_PER_REQUEST billing and do not require autoscaling configuration.

Build docs developers (and LLMs) love