> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Trade-offs in AWS DynamoDB

> Choose a DynamoDB backend from your application's transactions, indexes, numeric values, traffic and recovery requirements.

Cloud Adapter lets your application keep its DynamoDB client, requests and item types for the operations documented by the selected adapter. The backend determines how it stores those items, maintains indexes and commits changes. Choose from the operations and guarantees your application needs, then compare the capacity and operating costs of the candidates that fit. The OCI section below identifies a cataloged target whose documented contract requires native application access instead of a DynamoDB endpoint.

## General trade-offs

First establish where the data must run. Then compare the DynamoDB adapters available in that environment. An adapter includes both the DynamoDB origin and a particular target service; a larger backend does not supply an operation outside that mapping's contract.

The [DynamoDB service catalog](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table) gives operation-level coverage. The sections below separate workload choices within each environment from the general requirements that apply to all of them.

### Application requirements

Before choosing, answer these questions:

* Which requests need atomic changes across several items or tables?
* Which GSI/LSI queries, sort orders and filters does the application actually use?
* Must numeric values preserve DynamoDB's full decimal precision?
* Does another component consume DynamoDB Streams or depend on per-item TTL?
* Are keys distributed, or does most traffic contend on a few items?
* Who else shares the database, cluster, connection budget and recovery procedure?

Keep index declaration and runtime traffic separate. Use the selected profile's index-creation lifecycle and verify index readiness before serving its queries. Runtime table creation and deployment-time schema preparation differ by mapping.

### Who operates the chosen architecture?

For these examples, your platform team operates Cloud Adapter and target account; your application team owns business correctness. These assignments do not imply a Tensor9 managed-operations service.

| Component                        | Provisioning, capacity and alerts                                                          | Upgrades and recovery                                                                                          | Access needed                                                          |
| -------------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| Cloud Adapter runtime            | Platform team owns deployment, process health and connection/concurrency budgets           | Platform team upgrades the runtime and restores its configured durable state                                   | Deployment access, runtime identity and state-store access             |
| Managed backend                  | Platform team selects/pays for capacity; the provider operates the managed infrastructure  | The provider supplies native service mechanisms; platform team configures backups and performs recovery drills | Provider permissions for configuration, monitoring and restore         |
| Item/index and resource metadata | Application team defines required behavior; platform team monitors storage/index readiness | Restore authoritative data and adapter metadata coherently; rebuild only indexes documented as rebuildable     | Data/schema access appropriate to the chosen mapping                   |
| Application and cutover          | Application team owns latency budgets, retries and migration reconciliation                | Application team verifies restored business state and authorizes traffic changes                               | Test clients, sanitized request evidence and business-state visibility |

Two logical tables can share one physical capacity or failure boundary. Do not assume separate names mean independent instances. Consult [configuration](/cloud-adapter/configuration/files#when-to-add-a-service-entry) for pre-provisioned bindings and [operations](/cloud-adapter/operations/overview) for the deployment's operating procedures.

## Google Cloud

### Firestore, Cloud SQL PostgreSQL, Spanner and Bigtable

These four mappings offer different numeric, transaction, indexing and capacity models in the same target environment. Compare candidates against the same item values, request mix and recovery requirements.

| Backend                                                                                                              | How it implements DynamoDB behavior                                         | Consequence for the application and operator                                                                                                                        |
| -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Firestore](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#firestore)                           | Documents, maintained composite indexes and cross-document transactions     | Conditional updates can read before writing and repeat under contention. Signed 64-bit integers remain exact; other numbers must fit the documented numeric domain. |
| [Cloud SQL PostgreSQL](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#cloud-sql-for-postgresql) | Typed item storage, native indexes, row locks and serializable transactions | Exact DynamoDB decimals and multi-item transactions fit. Connections, lock contention, storage and the provisioned instance are shared capacity concerns.           |
| [Spanner](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#cloud-spanner)                         | Native tables/indexes and cross-table read-write transactions               | Exact decimals, indexes and distributed transactions fit, with provisioned instance capacity and a replicated commit path.                                          |
| [Bigtable](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#cloud-bigtable)                       | One item per row, direct mutations and guarded row updates                  | A narrow key-value mapping with row-level atomicity. Secondary indexes, multi-item transactions, DynamoDB Streams and per-item TTL are not part of this mapping.    |

<div style={{ maxWidth: "480px", margin: "1.5rem auto" }}>
  <img className="t9-diagram-light" src="https://mintcdn.com/tensor9/n9C52EeVXETMoe0e/images/diagrams/tradeoffs-dynamodb-light.svg?fit=max&auto=format&n=n9C52EeVXETMoe0e&q=85&s=ad2776080272750fe83ace521c1292e9" alt="Choose between Cloud SQL's serializable transaction path and Bigtable's row-local key-value path behind the DynamoDB adapter; the two backends are alternatives." width="480" height="582" data-path="images/diagrams/tradeoffs-dynamodb-light.svg" />

  <img className="t9-diagram-dark" src="https://mintcdn.com/tensor9/n9C52EeVXETMoe0e/images/diagrams/tradeoffs-dynamodb-dark.svg?fit=max&auto=format&n=n9C52EeVXETMoe0e&q=85&s=1a0a15f88dd15edd560cef07c58386df" alt="Choose between Cloud SQL's serializable transaction path and Bigtable's row-local key-value path behind the DynamoDB adapter; the two backends are alternatives." width="480" height="582" data-path="images/diagrams/tradeoffs-dynamodb-dark.svg" />
</div>

### Tenant metadata with quiet periods

Consider a tenant directory in Google Cloud: small records, point reads by tenant ID, lookup by email and conditional profile updates. Nights are quiet. The application uses ordinary counts and timestamps, not arbitrary-precision financial values.

Compare **DynamoDB → Firestore** with **DynamoDB → Cloud SQL PostgreSQL**. In the [Firestore mapping](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#firestore), Cloud Adapter stores typed documents and uses maintained composite indexes for secondary lookups, rather than scanning every document to answer an indexed query. The PostgreSQL mapping uses typed item storage and native indexes. Both retain the application's DynamoDB calls within their documented contracts.

Cloud SQL commits provisioned database capacity even during quiet periods; that capacity can also serve a sustained or shared workload. Firestore's request and index work instead matters to the comparison. A conditional update may read the document, evaluate the condition and retry after a competing write. Include that work, idle capacity, storage and operating effort in both budgets.

Firestore also supports cross-document transactions; needing more than one item does not automatically eliminate it. Numeric representation is a separate question. Values outside Firestore's accepted numeric range exclude that mapping for requests requiring those exact values; PostgreSQL preserves the documented DynamoDB decimal domain. Compare the actual values, transaction contention and traffic duty cycle rather than inferring a cost result from either storage model.

**Comparison record:** Google Cloud; intermittent metadata; Firestore request/index work and document contention versus Cloud SQL provisioned capacity, connections and transaction contention. The application team owns index rollout and retry behavior; the platform team owns access, budgets and recovery for either option. Test actual update shapes and both key lookups on each candidate, retaining cost and correctness observations separately. For migration, copy a representative tenant and account for writes during the copy before moving traffic.

### Orders, inventory and exact amounts

A regional order service updates an order and its inventory record together. A failed condition must leave both unchanged. Amounts must retain their decimal value. DynamoDB Streams is not required for this transaction path.

Compare **DynamoDB → Cloud SQL PostgreSQL** with **DynamoDB → Spanner**. On PostgreSQL, Cloud Adapter evaluates the conditions and commits the item changes inside one serializable database transaction. The application still sends `TransactWriteItems`; it does not become a SQL application.

PostgreSQL's instance capacity, storage and connections are shared budgets. Contention can produce retryable transaction conflicts, so test hot stock records, not only unrelated orders. The [PostgreSQL pool guidance](/cloud-adapter/tuning/aws-dynamodb#postgresql-budget-the-shared-connection-pool) explains why adding adapter processes without budgeting their connections can make matters worse.

Spanner preserves exact DynamoDB numeric values and implements cross-table transactions and native secondary indexes, with provisioned capacity and a replicated commit path. Compare its transaction placement and capacity model with PostgreSQL's instance, lock and connection boundaries using the same transaction mix and deployment locality; single-item throughput does not predict transaction latency.

The PostgreSQL transaction contract examined here excludes stream-enabled tables. Spanner's mapping also does not serve DynamoDB Streams. If transactions and change capture are both hard requirements, neither described path satisfies that combination; examine the documented combined contract of other mappings.

**Comparison record:** Google Cloud; exact-value order transactions; Cloud SQL instance/connection/lock budgets versus Spanner provisioned capacity and replicated transactions. The platform team owns database capacity and recovery, and the application team owns contention handling and acceptance tests for either candidate. The check below illustrates the transaction assertions on Cloud SQL; repeat the same assertions through the configured Spanner adapter to compare observations. Migration must preserve exact values and catch up writes before cutover; keeping the old database does not undo new target writes.

### Independent key-value records

A device-state service stores independent records under widely distributed keys. It reads by primary key, mostly writes unconditionally and needs neither secondary indexes, cross-item transactions, Streams nor per-item TTL.

Compare **DynamoDB → Bigtable** with **DynamoDB → Spanner**. Bigtable's row-local mapping stores one item per row, and eligible writes avoid fetching its previous contents. Conditions and more complex updates use a guarded read-modify-write path. Spanner stores items in native tables with a transaction and secondary-index model.

Bigtable requires provisioned cluster capacity and exposes the narrower API contract described above. Adding nodes does not split a single hot item. Measure real item sizes, skew and conditional writes alongside the uniform-key case. The Bigtable mapping also relaxes the aggregate item-size check for eligible blind updates; it does not suit applications that depend on that exact rejection behavior.

Secondary-key queries or atomic multi-item changes are supported by the described Spanner mapping but excluded from the Bigtable mapping. Those are contract differences, not settings that a larger Bigtable instance can supply. If Streams becomes required, consult another qualifying profile rather than assuming Spanner supplies it.

**Comparison record:** Google Cloud; independent base-key records; Bigtable row-local mutation and cluster capacity versus Spanner transactions, indexes and instance capacity. Measure each with the same key skew and conditional-update mix. For Bigtable, prepare the physical table, column families and verified single-cluster application profile before serving logical tables. For Spanner, verify the configured schema and indexes. Load and compare records before cutover; neither described mapping supplies a Streams-based catch-up path.

### Try the Cloud SQL transaction path

This disposable check demonstrates a rejected transaction, an accepted transaction and an identical retry against an **installed test endpoint**. Cloud SQL is the concrete test fixture, not a backend recommendation. It is a client-side check, not a backend installation procedure or production load test. The backend is a real Google Cloud database.

<Steps>
  <Step title="Confirm the installed mapping and its contract">
    Ask the deployment owner for an isolated endpoint whose table-creation path selects `google::1.0.0::cloudsql::postgresql`, the origin credential profile and region accepted there, and permission to create and delete disposable tables. The owner must have prepared the Cloud SQL database, its connection binding, runtime identity and durable adapter state. Confirm the effective mapping with that owner; a profile lookup does not identify a running endpoint's backend.

    Install the Tensor9 CLI, and have the AWS CLI and Python with `boto3` available:

    ```bash theme={null}
    brew tap tensor9ine/tensor9
    brew install tensor9
    tensor9 --version
    ```

    Use origin credentials authorized at your adapter endpoint; Google Cloud backend credentials belong to the adapter.

    ```bash theme={null}
    tensor9 explain \
      -origin aws::1.0.0::dynamodb::table \
      -target google::1.0.0::cloudsql::postgresql \
      -operation TransactWriteItems \
      -fmt Human
    ```

    This inspects the directed profile without executing a cloud request.
  </Step>

  <Step title="Set the test client's endpoint">
    Set the installed test endpoint and the origin authentication settings supplied by its owner:

    ```bash theme={null}
    export AWS_ENDPOINT_URL_DYNAMODB="<installed Cloud SQL-backed DynamoDB test endpoint>"
    export AWS_PROFILE="<origin test credential profile>"
    export AWS_REGION="<origin region accepted by the endpoint>"
    ```

    The service-specific variable routes DynamoDB clients in this process. With it set, `boto3.client("dynamodb", region_name=os.environ["AWS_REGION"])` uses that endpoint. To scope the choice to one client, pass it explicitly instead, as the script below does. Other AWS service clients remain unchanged.
  </Step>

  <Step title="Check access before creating data">
    Run one bounded, read-only catalog request:

    ```bash theme={null}
    aws dynamodb list-tables --limit 1 --no-paginate
    ```

    Expect a DynamoDB response containing a `TableNames` list, which can be empty. This checks endpoint reachability, origin authorization and access to the adapter's table catalog. It does not prove native database write access or transaction readiness. If it fails, resolve the endpoint, identity or catalog error before proceeding. The next step's table creation, waiter and item writes exercise the selected backend before the transaction assertions.
  </Step>

  <Step title="Run the complete transaction check">
    Save this as `check-dynamodb-tradeoffs.py`, replace the endpoint with your installed test endpoint, then run `python check-dynamodb-tradeoffs.py`. It creates `tradeoffs-orders` with Streams disabled and leaves it available for inspection. Use an isolated test environment where that table does not already exist. If creation reports that it exists, stop; do not reuse or delete someone else's table.

    ```python theme={null}
    import os
    import uuid
    from decimal import Decimal

    import boto3
    from botocore.exceptions import ClientError

    dynamodb = boto3.client(
        "dynamodb",
        endpoint_url="<installed Cloud SQL-backed DynamoDB test endpoint>",
        region_name=os.environ["AWS_REGION"],
    )
    table = "tradeoffs-orders"
    print("Disposable table:", table, flush=True)
    dynamodb.create_table(
        TableName=table,
        AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}],
        KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
        BillingMode="PAY_PER_REQUEST",
        StreamSpecification={"StreamEnabled": False},
    )
    dynamodb.get_waiter("table_exists").wait(TableName=table)
    amount = "12345678901234567890.12"
    dynamodb.put_item(TableName=table, Item={
        "id": {"S": "order-1"}, "status": {"S": "pending"},
        "amount": {"N": amount},
    })
    dynamodb.put_item(TableName=table, Item={
        "id": {"S": "stock-1"}, "quantity": {"N": "1"},
    })

    def read_state():
        def read(key):
            return dynamodb.get_item(
                TableName=table, Key={"id": {"S": key}},
                ConsistentRead=True,
            )["Item"]
        order, stock = read("order-1"), read("stock-1")
        assert Decimal(order["amount"]["N"]) == Decimal(amount)
        return order["status"]["S"], Decimal(stock["quantity"]["N"])

    def transaction(expected_status):
        return [
            {"Update": {
                "TableName": table, "Key": {"id": {"S": "order-1"}},
                "UpdateExpression": "SET #s = :paid",
                "ConditionExpression": "#s = :expected",
                "ExpressionAttributeNames": {"#s": "status"},
                "ExpressionAttributeValues": {
                    ":paid": {"S": "paid"},
                    ":expected": {"S": expected_status},
                },
            }},
            {"Update": {
                "TableName": table, "Key": {"id": {"S": "stock-1"}},
                "UpdateExpression": "SET #q = #q - :one",
                "ConditionExpression": "#q >= :one",
                "ExpressionAttributeNames": {"#q": "quantity"},
                "ExpressionAttributeValues": {":one": {"N": "1"}},
            }},
        ]

    try:
        dynamodb.transact_write_items(
            TransactItems=transaction("not-the-current-status"),
            ClientRequestToken=str(uuid.uuid4()),
        )
    except ClientError as error:
        if error.response["Error"]["Code"] != "TransactionCanceledException":
            raise
    else:
        raise AssertionError("The false condition was accepted")
    assert read_state() == ("pending", Decimal("1"))

    request = {
        "TransactItems": transaction("pending"),
        "ClientRequestToken": str(uuid.uuid4()),
    }
    dynamodb.transact_write_items(**request)
    assert read_state() == ("paid", Decimal("0"))
    dynamodb.transact_write_items(**request)
    assert read_state() == ("paid", Decimal("0"))
    print("Checks passed; inspect and clean up:", table)
    ```

    Repeat the identical request promptly. DynamoDB's [request-token contract](https://docs.aws.amazon.com/boto3/latest/reference/services/dynamodb/client/transact_write_items.html) provides a ten-minute idempotency window; changing parameters while reusing the token is a different test.
  </Step>

  <Step title="Interpret the observations">
    Expected observations, not captured benchmark output:

    * The false condition rejects the transaction; order and stock remain unchanged.
    * The valid transaction changes both items, preserving the exact amount.
    * The immediate identical retry leaves stock at zero and the order paid.

    Unexpected changes stop acceptance of this tested path. Preserve the table name, request IDs and actual values, then follow [adapter debugging](/cloud-adapter/debugging/overview). An authentication or connection error is not a transaction result. Inspect the selected mapping with [Explain](/cloud-adapter/debugging/explain); an explanation supplements the state check rather than replacing it. `x-t9-explain: true` executes a request, so do not replay mutations just to collect a report.

    After this check, [qualify contention and recovery](/cloud-adapter/local-testing/testing-your-adapters) with representative data, including ambiguous network failures, adapter restart and database failover. The sequential reads above do not prove isolation for concurrent readers.
  </Step>

  <Step title="Clean up only the experiment">
    Confirm the endpoint still points at the installed test adapter and that this run created `tradeoffs-orders`, then inspect and delete that table:

    ```bash theme={null}
    aws dynamodb describe-table --table-name tradeoffs-orders
    aws dynamodb delete-table --table-name tradeoffs-orders
    aws dynamodb wait table-not-exists --table-name tradeoffs-orders
    ```

    Keep evidence before deletion if a check failed. Do not stop a shared adapter or remove its database. Deleting this logical table does not retire the Cloud SQL instance or stop its charges; let the infrastructure owner remove any dedicated test database, backups or instance when no other test depends on them.
  </Step>
</Steps>

## Microsoft Azure

### Cosmos DB options and workload fit

| Backend                                                                                                                  | Strength for a matching workload                                                                        | Limits and costs to account for                                                                                                                                  |
| ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Provisioned Cosmos DB](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#azure-cosmos-db-provisioned) | Explicit throughput allocation and a managed GSI path for secondary-key queries                         | Capacity and index work consume RUs; partition skew can throttle one part of the workload. Native numeric values have a narrower precision domain than DynamoDB. |
| [Serverless Cosmos DB](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#azure-cosmos-db-serverless)   | Consumption-based capacity for eligible point-read, base-table and LSI workloads with variable activity | No GSI mapping. Numeric, transaction and partition constraints still apply; account mode is not a table-level billing-mode switch.                               |

Neither option supplies the full DynamoDB multi-item transaction contract. Reject a mapping if required numeric values, transaction shapes or indexes fall outside its profile before comparing its cost. A quiet workload alone does not determine the choice.

### Azure: provisioned or serverless Cosmos DB?

Consider a nontransactional tenant directory in Azure: point reads, conditional single-item updates and quiet nights. Compare `azure::1.0.0::cosmosdb::serverless` with `azure::1.0.0::cosmosdb::provisioned` using the same traffic trace and item sizes.

The **provisioned Cosmos DB** mapping provides a managed DynamoDB GSI path; the serverless mapping does not. A required GSI therefore excludes serverless for that workload. For supported base-table/LSI operations, compare serverless consumption with provisioned capacity using the same duty cycle. Neither throughput mode alone establishes a multi-item transaction contract.

Provisioned capacity buys an explicit RU budget, not immunity to partition heat. Compare conditional-update work, index amplification and demand across partition keys. A hot partition can throttle while other capacity is idle. Serverless consumption also has capacity limits; measure bursts and completed work, not only the quiet-period bill.

**Comparison record:** Azure placement; provisioned RU allocation and managed GSI behavior versus serverless consumption and its supported base-table/LSI contract. Record any excluded operations before comparing capacity, partition heat and total cost. The platform team owns account mode, container capacity and alerts for either deployment. Account mode is distinct from a table's throughput allocation: logical tables sharing a container share its budget. DynamoDB `BillingMode` does not switch the Cosmos account mode, and a backend tag does not migrate data. Changing modes requires a documented account/container migration and cutback procedure, including index rebuild and writes accepted after cutover. Continue with the [Cosmos comparison](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#on-azure) and [capacity examples](/cloud-adapter/tuning/aws-dynamodb#provisioned-cosmos-db-give-a-table-its-own-capacity).

## Scaleway

### Managed PostgreSQL or CloudNativePG

The catalog offers [Scaleway Managed Database for PostgreSQL](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#scaleway-managed-database-for-postgresql) and [CloudNativePG](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#cloudnativepg). Both use PostgreSQL-backed DynamoDB item storage. The choice concerns where the database runs and who maintains its infrastructure, alongside the supported transaction, index and Streams combinations.

| Backend                     | When its strengths matter                                                                                      | Trade-offs to accept and verify                                                                                                                                                                      |
| --------------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Scaleway managed PostgreSQL | Database infrastructure outside the application's Kubernetes cluster, with provider-managed hosting            | Provisioned server capacity, connection limits, maintenance and recovery settings remain deployment decisions. Verify failover and backup restoration with the adapter's item and resource metadata. |
| CloudNativePG               | Database placement within the customer's Kubernetes infrastructure, with control over its storage and topology | The deployment needs capacity for PostgreSQL, persistent volumes, backups and recovery. Cluster-local storage and the application can share failure domains.                                         |

For an order service requiring exact amounts and atomic changes, run the transaction assertions from the Google Cloud example through the Scaleway endpoint whose selected mapping documents that contract. For a stream consumer, separately verify the profile's stream-writer restrictions and recovery behavior. A managed host and a cluster-local host are not interchangeable backup plans.

## Akamai

### CloudNativePG

The documented DynamoDB target is [CloudNativePG](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#cloudnativepg). It keeps the PostgreSQL store with the Cloud Adapter deployment and preserves the profile's exact decimal, conditional-write and secondary-index behavior.

This option fits an Akamai placement requirement when the application can use that PostgreSQL-backed contract and the deployment has suitable persistent storage. Budget connections and lock contention for concurrent transactions; confirm the combined Streams/transaction restrictions. There is no second documented DynamoDB backend here to rank against it. If a required behavior is excluded, revisit the application or placement requirement rather than assuming another Akamai database is a drop-in adapter.

## DigitalOcean

### CloudNativePG

The documented DynamoDB mapping uses [CloudNativePG](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#cloudnativepg), not an arbitrary DigitalOcean database. It is a candidate for applications that need DynamoDB clients and PostgreSQL-backed item semantics while keeping data in their DigitalOcean deployment.

The operating cost includes database compute, persistent storage, backup capacity and the connections used by every adapter instance. Test a hot record alongside unrelated traffic, then restore both item tables and the adapter's table/index metadata. Choose this mapping when its contract and cluster operating responsibilities fit; a requirement for provider-operated database infrastructure would require a different documented placement or adapter.

## Private Kubernetes

### CloudNativePG and customer-owned infrastructure

[CloudNativePG](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#cloudnativepg) supports customer-owned and disconnected infrastructure. The application can retain the documented DynamoDB API behavior without relying on a public managed database.

Control over placement also means specifying storage durability, replica placement, spare capacity and off-cluster recovery. Size the database for schema/index changes as well as item requests. If policy prohibits data leaving the site, put backup and restore procedures within the permitted boundary and rehearse a cluster loss. The Google Cloud transaction probe can supply the business assertions after an operator prepares the corresponding PostgreSQL-backed endpoint; its Google Cloud provisioning assumptions do not apply here.

## OCI

### OCI NoSQL requires native application access

[OCI NoSQL Database](/cloud-adapter/service-catalog/aws/databases-storage/dynamodb-table#oci-nosql-database) provides a target-native table and capacity model, but this mapping does **not** provide a DynamoDB runtime endpoint. It can fit a move to OCI when the application team accepts OCI-native reads, writes and queries. It does not fit a requirement to retain the DynamoDB SDK request path.

The mapping converts the declared primary keys and capacity mode. OCI requires an explicit storage cap; DynamoDB units do not establish an equivalent OCI workload budget. Declared DynamoDB GSIs/LSIs, per-item TTL and Streams require separate application and target-service work. Inventory those dependencies before choosing this path, then test the converted data layout, queries, expiry and recovery through the native API. Do not run the DynamoDB client probe against OCI NoSQL and interpret failure as a sizing problem.

## Next steps

Keep the decision record with your configuration: selected mapping, shared resources, acceptance observations, operating owners and the requirement that would cause you to reconsider it.

Next, follow [Tuning AWS DynamoDB](/cloud-adapter/tuning/aws-dynamodb) to size backend capacity, configure adapter connections and measure the effect on your workload.
