> ## 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.

# Data storage

> DynamoDB tables and S3 buckets used in PayPulse Cloud.

PayPulse Cloud uses two storage technologies: DynamoDB for structured invoice and user data, and S3 for raw invoice files and Lambda deployment artifacts.

## DynamoDB tables

There are 11 DynamoDB tables in total. All tables have server-side encryption enabled.

### `RentalInvoices`

Stores parsed rental invoice data. This is the primary table for rental invoice records.

| Property               | Value                                                                         |
| ---------------------- | ----------------------------------------------------------------------------- |
| Partition key          | `UserID` (String)                                                             |
| Sort key               | `InvoiceID` (String)                                                          |
| Billing mode           | Provisioned (5 read / 5 write capacity units, autoscaling 1–10 at 70% target) |
| Stream                 | Enabled — `NEW_AND_OLD_IMAGES`                                                |
| Point-in-time recovery | Disabled                                                                      |

**GSI:** `due_date_year-due_date_month-index`

* Hash key: `due_date_year` (String)
* Range key: `due_date_month` (String)
* Projection: ALL

<Note>
  The DynamoDB stream on `RentalInvoices` is what triggers `send_invoice_notification` on every new INSERT. See [Event flow](/architecture/event-flow) for the full pipeline.
</Note>

### `Users`

Stores user account information including a `last_retail_invoice_fetch` timestamp used for incremental retail invoice ingestion.

| Property      | Value             |
| ------------- | ----------------- |
| Partition key | `UserID` (String) |
| Billing mode  | Pay per request   |
| Stream        | Disabled          |

**GSI:** `Email-index`

* Hash key: `Email` (String)
* Projection: ALL

### `RetailInvoices` (base table)

The base table for all retail invoice records, regardless of category. Detail tables (below) store category-specific fields keyed by `InvoiceID`.

| Property               | Value                          |
| ---------------------- | ------------------------------ |
| Partition key          | `UserID` (String)              |
| Sort key               | `InvoiceID` (String)           |
| Billing mode           | Pay per request                |
| Stream                 | Enabled — `NEW_AND_OLD_IMAGES` |
| Point-in-time recovery | Enabled                        |

**GSI-1:** `invoice_date-index`

* Hash key: `UserID` (String)
* Range key: `invoice_date` (String)
* Projection: ALL
* Use: date-range queries for a single user

**GSI-2:** `sub_type-invoice_date-index`

* Hash key: `UserID_SubType` (String, composite of `UserID` + `_` + `sub_type`, e.g. `user_abc123_food-delivery`)
* Range key: `invoice_date` (String)
* Projection: ALL
* Use: category + date queries (e.g., "all grocery invoices in March")

Common fields include: `vendor_name`, `sub_type`, `total_amount`, `currency`, `invoice_date`, `s3_path`.

### Retail invoice detail tables

Each retail category has its own detail table. All eight share the same schema.

| Table name                     | Category                                         |
| ------------------------------ | ------------------------------------------------ |
| `FoodDeliveryInvoices`         | Restaurants and food delivery orders             |
| `ClothingInvoices`             | Clothing and fashion purchases                   |
| `TechnologyInvoices`           | Electronics and tech products                    |
| `SubscriptionInvoices`         | Streaming services and memberships               |
| `GroceryInvoices`              | Supermarket purchases                            |
| `MiscellaneousUtilityInvoices` | Utility bills (electricity, water, internet)     |
| `MiscellaneousInvoices`        | Other retail purchases                           |
| `TravelInvoices`               | Transportation invoices (flights, trains, buses) |

All detail tables use:

* Partition key: `InvoiceID` (String)
* Billing mode: Pay per request
* Server-side encryption: Enabled

### `VendorConfig`

Drives automated retail invoice fetching. Adding a row here is all that is needed to start fetching invoices from a new vendor — no code changes required.

| Property      | Value                |
| ------------- | -------------------- |
| Partition key | `vendor_id` (String) |
| Billing mode  | Pay per request      |

Common fields include: `vendor_name`, `invoice_sub_type`, `email_patterns`, `subject_keywords`, `parser_type`, `active` (boolean).

## S3 buckets

### `rental-invoices-bucket`

Stores all invoice files fetched from Gmail. Versioning is enabled and all public access is blocked. Encryption uses AES-256 (SSE-S3).

**Rental invoices (PDF):**

```
rental-invoices-bucket/invoices/{user_id}/rental/{filename}.pdf
```

Example:

```
invoices/user_a1b2c3d4/rental/invoice_0001.pdf
```

**Retail invoices (HTML):**

```
rental-invoices-bucket/invoices/{user_id}/retail/{sub_type}/{vendor}_{date}_{hash}.html
```

The `{sub_type}` path segment is one of:

| `sub_type`      | Description                                            |
| --------------- | ------------------------------------------------------ |
| `food-delivery` | Restaurant and food delivery orders                    |
| `clothing`      | Clothing and fashion purchases                         |
| `technology`    | Electronics and tech products                          |
| `subscriptions` | Streaming services and memberships                     |
| `grocery`       | Grocery store purchases                                |
| `utility`       | Utility bills (electricity, water, etc.)               |
| `miscellaneous` | Other retail purchases                                 |
| `travel`        | Transportation invoices (flights, trains, buses, etc.) |

`{user_id}` is a UUID prefixed with `user_`, generated at signup.

**S3 event notifications:**

| Filter                             | Trigger                               |
| ---------------------------------- | ------------------------------------- |
| Prefix `invoices/`, suffix `.pdf`  | Invokes `parse_invoice` Lambda        |
| Prefix `invoices/`, suffix `.html` | Invokes `parse_retail_invoice` Lambda |

### Lambda functions bucket

Contains the deployment ZIP archives for all ZIP-based Lambda functions. Versioning is enabled. Lambda has `s3:GetObject` permission via a bucket policy.

Functions deployed from this bucket:

* `fetch_invoices`
* `fetch_latest_invoice`
* `fetch_retail_invoices`
* `send_invoice_notification`
* `get_rental_invoice`
* `get_rental_invoices`
* `delete_user`
* `get_user_profile`
* `login_user`
* `signup_user`
* `gmail_store_tokens`

<Tip>
  When you upload a new ZIP version, Terraform detects the updated S3 object version and re-deploys the function automatically on the next `terraform apply`.
</Tip>
