Skip to content
cloudemu
Services

Database

In-memory NoSQL document/key-value store modelled on DynamoDB, Cosmos DB, and Firestore, driven with the real cloud SDKs

aws DynamoDBazr Cosmos DBgcp Firestore

Emulates a managed NoSQL store — the DynamoDB/Cosmos/Firestore table your app writes items to and queries by key. You create a table with a partition key (and optional sort key), then put, get, update, query, and scan schemaless items. Each item is just a map of attributes; the table indexes them by their key so lookups and range queries stay fast.

Reach for it in tests when your code puts an item and reads it back by key, runs a query with a key condition, or scans with a filter — so you can exercise those paths without a real DynamoDB account. For managed relational databases (RDS/Aurora, Azure SQL, Cloud SQL), see Relational Database instead.

ProviderServiceSDK-compatDriver
AWSDynamoDB✓ Liveaws.DynamoDB
AzureCosmos DB✓ Liveazure.CosmosDB
GCPFirestore✓ Livegcp.Firestore

Drive it with the real SDK#

The recommended path is to point the real SDK at the SDK-compat server, so your production data-access code runs unchanged. This creates a table keyed on id and writes one item — the client is the stock AWS SDK, only the endpoint is redirected:

import (
    "github.com/aws/aws-sdk-go-v2/service/dynamodb"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
    "github.com/stackshy/cloudemu/v2"
    awsserver "github.com/stackshy/cloudemu/v2/server/aws"
)

cloud := cloudemu.NewAWS()
ts := httptest.NewServer(awsserver.New(awsserver.Drivers{DynamoDB: cloud.DynamoDB}))

client := dynamodb.NewFromConfig(cfg, func(o *dynamodb.Options) {
    o.BaseEndpoint = aws.String(ts.URL)
})

client.CreateTable(ctx, &dynamodb.CreateTableInput{
    TableName: aws.String("Users"),
    AttributeDefinitions: []types.AttributeDefinition{
        {AttributeName: aws.String("id"), AttributeType: types.ScalarAttributeTypeS},
    },
    KeySchema: []types.KeySchemaElement{
        {AttributeName: aws.String("id"), KeyType: types.KeyTypeHash},
    },
    BillingMode: types.BillingModePayPerRequest,
})

client.PutItem(ctx, &dynamodb.PutItemInput{
    TableName: aws.String("Users"),
    Item: map[string]types.AttributeValue{
        "id":   &types.AttributeValueMemberS{Value: "u1"},
        "name": &types.AttributeValueMemberS{Value: "Alice"},
    },
})

Same shape with azcosmos (Azure) and cloud.google.com/go/firestore (GCP). See the SDK-Compat Server page for the full quick starts.

Call the driver directly#

For in-process setup or assertions you can skip the HTTP hop and call the driver. Items are plain map[string]any, so there's no attribute-value wrapping to deal with:

import dbdriver "github.com/stackshy/cloudemu/v2/services/database/driver"

aws.DynamoDB.CreateTable(ctx, dbdriver.TableConfig{
    Name: "Users", PartitionKey: "id",
})
aws.DynamoDB.PutItem(ctx, "Users", map[string]any{"id": "u1", "name": "Alice"})
item, _ := aws.DynamoDB.GetItem(ctx, "Users", map[string]any{"id": "u1"})

GetItem takes just the key attributes and returns the full item (or nil if absent). Query, Scan, UpdateItem, and batch/transactional writes take the same shape via dbdriver input structs.

Behavior & fidelity#

BehaviorWhat happens
Query and scan paginateResults come back in stable key order; pass a Limit and resume with an offset PageToken or a DynamoDB-style ExclusiveStartKey, and page tokens stay valid across calls.
Numeric-aware comparisonsNumbers order numerically ("10" > "9"), strings lexically, and bools false < true, matching the real services rather than naive string compare.
TTL expiry on readAn item past its TTL attribute reads as absent, so a Get or Query never returns expired data.
Streams / change feedWith streams enabled, writes emit INSERT / MODIFY / REMOVE records you can read back — useful for change-driven pipelines.
Global secondary indexesGSIs can be created, described, listed, and deleted, and a Query can target one via its IndexName.

SDK-compat — Live#

Real dynamodb, azcosmos, and Firestore clients drive it end-to-end — see SDK-Compat for the full operation list.

On this page

On this page