State API
The State API is used to save, read, and query key/value pairs in an underlying state store. Using a key/value store allows you to build stateful, persistent applications that save and retrieve their state for various business logic scenarios. See State API Reference.
Supported State Components
Currently, Catalyst supports 14 components that can be interchangably used with the State API.
In Catalyst, you can take advantage of Diagrid KV Store, a fully-managed Key-Value databse. It is created with a default component, but additional components can be configured.
Catalyst KV Store is only available through the Catalyst APIs.
- AWS DynamoDB: aws.dynamodb
- Azure Blob Storage: azure.blobstorage
- Azure Cosmos DB (SQL API): azure.cosmosdb
- Azure Table Storage: azure.tablestorage
- Apache Cassandra: cassandra
- Cloudflare Workers KV: cloudflare.workerskv
- CockroachDB: cockroachdb
- Memcached: memcached
- MongoDB: mongodb
- MySQL & MariaDB: mysql
- PostgreSQL: postgresql
- Redis: redis
- SQL Server: sqlserver
- Diagrid Key/Value Store: diagrid
Features
Below describe some of the features and characteristics of the Catalyst State API.
Configurable state store behaviors
With Catalyst, you can include additional metadata in a state operation request that describes how you expect the request to be handled. You can attach:
- Concurrency requirements
- Consistency requirements
By default, your application should assume a data store is eventually consistent and uses a last-write-wins concurrency pattern.
State components may vary in the capabilities they support, you can use the Catalyst console to filter by capability when determining the best state store for your use case.
Concurrency
Catalyst supports Optimistic Concurrency Control (OCC) using ETags. When a state value is requested, Dapr always attaches an ETag property to the returned state. When the user code:
- Updates a state item, it's expected to attach the ETag through the request body.
- Deletes a state item, it’s expected to attach the ETag through the
If-Match
header.
The write
operation succeeds when the provided ETag matches the ETag in the state store.
If your application omits ETags in writing requests, Dapr skips ETag checks while handling the requests. This enables the last-write-wins pattern, compared to the first-write-wins pattern with ETags.
Consistency
Catalyst supports both strong consistency and eventual consistency, with eventual consistency as the default behavior.
- Strong consistency: Catalyst waits for all replicas (or designated quorums) to acknowledge before it acknowledges a write request.
- Eventual consistency: Catalyst returns as soon as the write request is accepted by the underlying data store, even if this is a single replica.
Setting content type
State store components may maintain and manipulate data differently, depending on the content type. Catalyst supports passing content type with the State Management API as part of request metadata.
Setting the content type is optional, and the component decides whether to make use of it. Catalyst only provides the means of passing this information to the component.
- With the HTTP API: Set content type via URL query parameter
metadata.contentType
. For example,https://catalyst-project/v1.0/state/store?metadata.contentType=application/json
. - With the gRPC API: Set content type by adding key/value pair
"contentType" : <content type>
to the request metadata.
Multiple operations
Dapr supports two types of multi-read or multi-write operations: bulk or transactional. Read the API reference to learn how use bulk and multi options.
Bulk read operations
You can group multiple read requests into a bulk (or batch) operation. In the bulk operation, Catalyst submits the read requests as individual requests to the underlying data store, and returns them as a single result.
Transactional operations
You can group write, update, and delete operations into a request, which are then handled as an atomic transaction. The request will succeed or fail as a transactional set of operations.
Shared state between applications
Different applications have different needs when it comes to sharing state. In one scenario, you may want to encapsulate all state within a given application and have Catalyst manage the access for you. In another scenario, you may want two applications working on the same state to get and save the same keys.
Catalyst enables states to be:
- Isolated to an application
- Shared in a state store between applications
- Shared between multiple applications across different state stores
By default, all state keys are prefixed with the application's App ID before the state key <App ID>||<state key>
and are accessible only by the respective application.
To share application state across App IDs (and thus applications), set the keyPrefix
value on the infrastructure component. Supported key prefix strategies are documented here.
Enabling the outbox pattern
Catalyst enables developers to use the Dapr outbox pattern for achieving a single transaction across a transactional state store and any message broker.
A tutorial for using the outbox pattern is in-progress! Stay tuned.
Query API
Using the optional state management Query API, you can query the key/value data saved in state stores, regardless of underlying database or storage technology. With the state management Query API, you can filter, sort, and paginate the key/value data.
The Query API is not supported by all state stores.
State Time-to-Live (TTL)
Dapr enables per state item request time-to-live (TTL). This means that applications can set time-to-live per state item stored, and these state items cannot be retrieved after expiration.
Try the State API
Walk through the following quickstart to see State in action:
Quickstart/tutorial | Description |
---|---|
State API Quickstart | Manage key-value pairs using Diagrid KV Store |