Tables
Tables store application records as keyed JSON documents. Use them for user profiles, session state, idempotency keys, and other items you look up by a primary key. Query by key or index, write with conditions, and change several items in one transaction.
Call it with skippr tables. Wire clients use native CloudTables.* requests; a stock DynamoDB SDK is not a supported client. If you already model data that way, see Tables for DynamoDB users.
Status: Preview. See the API action reference for the full command list.
At a glance
| Need | Use |
|---|---|
| Address one item | Partition key, with an optional sort key |
| Read an ordered key range | Query; use Scan only when no key access pattern fits |
| Prevent an overwrite or race | ConditionExpression on PutItem, UpdateItem, or DeleteItem |
| Change multiple items atomically | TransactWriteItems |
| Read multiple items atomically | TransactGetItems |
| Query another access pattern | A global secondary index (GSI) |
| Expire items | UpdateTimeToLive with an epoch-seconds number attribute |
Prerequisites
- A Cloud access JWT from Cloud User Directory, or Cloud access-key credentials for SigV4.
- A policy that permits the required
tables:<Operation>actions. - For SigV4, use service code
tablesand the endpoint's region.
Sign in with skippr login, then create a table with a partition key. The same create is CLI, Terraform, CDKTF TypeScript, or CDKTF Python. For provider credentials and the shared cloud provider block, see Terraform and CDKTF.
skippr tables create-table --table-name notes --input - <<JSON
{
"attributeDefinitions": [
{ "attributeName": "pk", "attributeType": "S" }
],
"keySchema": [
{ "attributeName": "pk", "keyType": "HASH" }
]
}
JSONresource "cloud_table" "notes" {
table_name = "notes"
hash_key = "pk"
}import { CloudProvider, CloudTable } from "@skippr/provider-cloud";
const cloud = new CloudProvider(this, "cloud", { region: "eu-central-1" });
new CloudTable(this, "notes", {
tableName: "notes",
hashKey: "pk",
provider: cloud,
});from skippr_cdktf import CloudProvider, CloudTable
cloud = CloudProvider(self, "cloud", region="eu-central-1")
CloudTable(
self,
"notes",
table_name="notes",
hash_key="pk",
provider=cloud,
)Access and wire contract
| Fact | Value |
|---|---|
| CLI | skippr tables <operation> |
| Endpoint | https://tables.{region}.cloud.skippr.io/ |
| Method | POST |
| Content type | application/json |
| Target | X-Cloud-Target: CloudTables.<Operation> |
| Authentication | Bearer JWT, or SigV4 with service tables |
| JSON naming | lower camel case, such as tableName and lastEvaluatedKey |
| Item values | Typed objects: S, N, B, BOOL, NULL, M, L, SS, NS, BS |
Operations by task
Manage tables and indexes
| Task | Operations | Notes |
|---|---|---|
| Create and inspect | CreateTable, DescribeTable, ListTables | Partition-only and partition-plus-sort schemas are supported |
| Change a table | UpdateTable | Add or remove GSIs; throughput values are accepted as no-ops |
| Remove a table | DeleteTable | Fails when the table does not exist |
| Configure expiry | UpdateTimeToLive, DescribeTimeToLive | Configures the item attribute used for TTL |
Read and write data
| Task | Operations | Notes |
|---|---|---|
| Point access | GetItem, PutItem, UpdateItem, DeleteItem | Conditional writes are supported |
| Key-range access | Query | Supports partition equality, sort-key conditions, ordering, and pagination |
| Full-table access | Scan | Paginated; usually more work than Query |
| Batch access | BatchGetItem, BatchWriteItem | Independent item operations; BatchGetItem is not a snapshot (≤100 keys); BatchWriteItem is not a transaction (≤25 ops) |
Use transactions
| Task | Operations | Notes |
|---|---|---|
| Atomic write | TransactWriteItems | Put, delete, and condition-check entries commit together or fail together |
| Atomic read | TransactGetItems | One snapshot of the requested items |
Behavior you need to handle
Conditions and missing data
- A false write condition returns
ConditionalCheckFailedException. - A missing table returns
ResourceNotFoundException. GetItemon a missing item succeeds without anitemmember; it is not a not-found error.- A failed transactional condition returns
TransactionCanceledExceptionwithdetails.cancellationReasons.
Pagination
Query and Scan default to 100 items and use pages of at most 1,000 items. When a response contains lastEvaluatedKey, send that value as exclusiveStartKey in the next request. Tokens are keys, not offsets; treat the returned key as continuation state and reuse it verbatim.
Retries and idempotency
The current Tables requests do not expose a clientToken. Do not assume an ambiguous failed mutation was deduplicated. PutItem replaces the item at the same key, while duplicate CreateTable returns ResourceInUseException. Use a condition such as attribute_not_exists(pk) when a repeated write must not overwrite existing data.
Strong reads and ignored capacity
All reads are strongly consistent. Sending consistentRead: false on GetItem, Query, Scan, or BatchGet produces an ignoredFields entry with reason strong_read_only. Omitting the field, or sending true, does not.
Provisioned throughput and capacity-unit values do not control Tables. If you send them, the response reports noop_capacity in ignoredFields; the optional x-cloud-ignored header may mirror the same array. Never use ConsumedCapacity as a billing or throttling signal.
Limits and errors
| Contract | Preview behavior |
|---|---|
| Item size | Maximum 400 KiB |
| Transaction size | Maximum 100 items per TransactWriteItems or TransactGetItems call |
| Query/scan page | Default 100; bounded to 1,000 items |
| Streams | DynamoDB Streams shard APIs are not offered; table stream configuration is planned |
| Error body | {"code":"…","message":"…","requestId":"…"} |
Validation failures, oversized items, failed conditions, missing tables, and transaction cancellations currently return HTTP 400 with the specific code in the JSON body. Unsupported targets return ValidationException.
