State management API reference

Detailed documentation on the state management API

Component file

A Dapr statestore.yaml component file has the following structure:

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: <NAME>
  namespace: <NAMESPACE>
spec:
  type: state.<TYPE>
  version: v1
  metadata:
  - name:<KEY>
    value:<VALUE>
  - name: <KEY>
    value: <VALUE>
Setting Description
metadata.name The name of the state store.
spec/metadata An open key value pair metadata that allows a binding to define connection properties.

Key scheme

Dapr state stores are key/value stores. To ensure data compatibility, Dapr requires these data stores follow a fixed key scheme. For general states, the key format is:

<App ID>||<state key>

For Actor states, the key format is:

<App ID>||<Actor type>||<Actor id>||<state key>

Save state

This endpoint lets you save an array of state objects.

HTTP Request

POST http://localhost:<daprPort>/v1.0/state/<storename>

URL Parameters

Parameter Description
daprPort The Dapr port
storename The metadata.name field in the user-configured statestore.yaml component file. Refer to the Dapr state store configuration structure mentioned above.

The optional request metadata is passed via URL query parameters. For example,

POST http://localhost:3500/v1.0/state/myStore?metadata.contentType=application/json

All URL parameters are case-sensitive.

Since || is a reserved string it cannot be used in the <state key> field.

Request Body

A JSON array of state objects. Each state object is comprised with the following fields:

Field Description
key State key
value State value, which can be any byte array
etag (optional) State ETag
metadata (optional) Additional key-value pairs to be passed to the state store
options (optional) State operation options; see state operation options

ETag format: Dapr runtime treats ETags as opaque strings. The exact ETag format is defined by the corresponding data store.

Metadata

Metadata can be sent via query parameters in the request’s URL. It must be prefixed with metadata., as shown below.

Parameter Description
metadata.ttlInSeconds The number of seconds for the message to expire, as described here

TTL: Only certain state stores support the TTL option, according the supported state stores.

HTTP Response

Response Codes

Code Description
204 State saved
400 State store is missing or misconfigured or malformed request
500 Failed to save state

Response Body

None.

Example

curl -X POST http://localhost:3500/v1.0/state/starwars?metadata.contentType=application/json \
  -H "Content-Type: application/json" \
  -d '[
        {
          "key": "weapon",
          "value": "DeathStar",
          "etag": "1234"
        },
        {
          "key": "planet",
          "value": {
            "name": "Tatooine"
          }
        }
      ]'

Get state

This endpoint lets you get the state for a specific key.

HTTP Request

GET http://localhost:<daprPort>/v1.0/state/<storename>/<key>

URL Parameters

Parameter Description
daprPort The Dapr port
storename metadata.name field in the user-configured statestore.yaml component file. Refer to the Dapr state store configuration structure mentioned above.
key The key of the desired state
consistency (optional) Read consistency mode; see state operation options
metadata (optional) Metadata as query parameters to the state store

The optional request metadata is passed via URL query parameters. For example,

GET http://localhost:3500/v1.0/state/myStore/myKey?metadata.contentType=application/json

Note, all URL parameters are case-sensitive.

HTTP Response

Response Codes

Code Description
200 Get state successful
204 Key is not found
400 State store is missing or misconfigured
500 Get state failed

Response Headers

Header Description
ETag ETag of returned value

Response Body

JSON-encoded value

Example

curl http://localhost:3500/v1.0/state/starwars/planet?metadata.contentType=application/json

The above command returns the state:

{
  "name": "Tatooine"
}

To pass metadata as query parameter:

GET http://localhost:3500/v1.0/state/starwars/planet?metadata.partitionKey=mypartitionKey&metadata.contentType=application/json

Get bulk state

This endpoint lets you get a list of values for a given list of keys.

HTTP Request

POST/PUT http://localhost:<daprPort>/v1.0/state/<storename>/bulk

URL Parameters

Parameter Description
daprPort The Dapr port
storename metadata.name field in the user-configured statestore.yaml component file. Refer to the Dapr state store configuration structure mentioned above.
metadata (optional) Metadata as query parameters to the state store

The optional request metadata is passed via URL query parameters. For example,

POST/PUT http://localhost:3500/v1.0/state/myStore/bulk?metadata.partitionKey=mypartitionKey

Note, all URL parameters are case-sensitive.

HTTP Response

Response Codes

Code Description
200 Get state successful
400 State store is missing or misconfigured
500 Get bulk state failed

Response Body

An array of JSON-encoded values

Example

curl http://localhost:3500/v1.0/state/myRedisStore/bulk \
  -H "Content-Type: application/json" \
  -d '{
          "keys": [ "key1", "key2" ],
          "parallelism": 10
      }'

The above command returns an array of key/value objects:

[
  {
    "key": "key1",
    "value": "value1",
    "etag": "1"
  },
  {
    "key": "key2",
    "value": "value2",
    "etag": "1"
  }
]

To pass metadata as query parameter:

POST http://localhost:3500/v1.0/state/myRedisStore/bulk?metadata.partitionKey=mypartitionKey

Delete state

This endpoint lets you delete the state for a specific key.

HTTP Request

DELETE http://localhost:<daprPort>/v1.0/state/<storename>/<key>

URL Parameters

Parameter Description
daprPort The Dapr port
storename metadata.name field in the user-configured statestore.yaml component file. Refer to the Dapr state store configuration structure mentioned above.
key The key of the desired state
concurrency (optional) Either first-write or last-write; see state operation options
consistency (optional) Either strong or eventual; see state operation options

The optional request metadata is passed via URL query parameters. For example,

DELETE http://localhost:3500/v1.0/state/myStore/myKey?metadata.contentType=application/json

Note, all URL parameters are case-sensitive.

Request Headers

Header Description
If-Match (Optional) ETag associated with the key to be deleted

HTTP Response

Response Codes

Code Description
204 Delete state successful
400 State store is missing or misconfigured
500 Delete state failed

Response Body

None.

Example

curl -X DELETE http://localhost:3500/v1.0/state/starwars/planet -H "If-Match: xxxxxxx"

Query state

This endpoint lets you query the key/value state.

HTTP Request

POST/PUT http://localhost:<daprPort>/v1.0-alpha1/state/<storename>/query

URL Parameters

Parameter Description
daprPort The Dapr port
storename metadata.name field in the user-configured statestore.yaml component file. Refer to the Dapr state store configuration structure mentioned above.
metadata (optional) Metadata as query parameters to the state store

The optional request metadata is passed via URL query parameters. For example,

POST http://localhost:3500/v1.0-alpha1/state/myStore/query?metadata.contentType=application/json

Note, all URL parameters are case-sensitive.

Response Codes

Code Description
200 State query successful
400 State store is missing or misconfigured
500 State query failed

Response Body

An array of JSON-encoded values

Example

curl -X POST http://localhost:3500/v1.0-alpha1/state/myStore/query?metadata.contentType=application/json \
  -H "Content-Type: application/json" \
  -d '{
        "filter": {
          "OR": [
            {
              "EQ": { "person.org": "Dev Ops" }
            },
            {
              "AND": [
                {
                  "EQ": { "person.org": "Finance" }
                },
                {
                  "IN": { "state": [ "CA", "WA" ] }
                }
              ]
            }
          ]
        },
        "sort": [
          {
            "key": "state",
            "order": "DESC"
          },
          {
            "key": "person.id"
          }
        ],
        "page": {
          "limit": 3
        }
      }'

The above command returns an array of objects along with a token:

{
  "results": [
    {
      "key": "1",
      "data": {
        "person": {
          "org": "Dev Ops",
          "id": 1036
        },
        "city": "Seattle",
        "state": "WA"
      },
      "etag": "6f54ad94-dfb9-46f0-a371-e42d550adb7d"
    },
    {
      "key": "4",
      "data": {
        "person": {
          "org": "Dev Ops",
          "id": 1042
        },
        "city": "Spokane",
        "state": "WA"
      },
      "etag": "7415707b-82ce-44d0-bf15-6dc6305af3b1"
    },
    {
      "key": "10",
      "data": {
        "person": {
          "org": "Dev Ops",
          "id": 1054
        },
        "city": "New York",
        "state": "NY"
      },
      "etag": "26bbba88-9461-48d1-8a35-db07c374e5aa"
    }
  ],
  "token": "3"
}

To pass metadata as query parameter:

POST http://localhost:3500/v1.0-alpha1/state/myStore/query?metadata.partitionKey=mypartitionKey

State transactions

Persists the changes to the state store as a transactional operation.

This API depends on a state store component that supports transactions.

Refer to the state store component spec for a full, current list of state stores that support transactions.

HTTP Request

POST/PUT http://localhost:<daprPort>/v1.0/state/<storename>/transaction

HTTP Response Codes

Code Description
204 Request successful
400 State store is missing or misconfigured or malformed request
500 Request failed

URL Parameters

Parameter Description
daprPort The Dapr port
storename metadata.name field in the user-configured statestore.yaml component file. Refer to the Dapr state store configuration structure mentioned above.

The optional request metadata is passed via URL query parameters. For example,

POST http://localhost:3500/v1.0/state/myStore/transaction?metadata.contentType=application/json

Note, all URL parameters are case-sensitive.

Request Body

Field Description
operations A JSON array of state operation
metadata (optional) The metadata for the transaction that applies to all operations

All transactional databases implement the following required operations:

Operation Description
upsert Adds or updates the value
delete Deletes the value

Each operation has an associated request that is comprised of the following fields:

Request Description
key State key
value State value, which can be any byte array
etag (optional) State ETag
metadata (optional) Additional key-value pairs to be passed to the state store that apply for this operation
options (optional) State operation options; see state operation options

Examples

The example below shows an upsert operation for key1 and a delete operation for key2. This is applied to the partition named ‘planet’ in the state store. Both operations either succeed or fail in the transaction.

curl -X POST http://localhost:3500/v1.0/state/starwars/transaction \
  -H "Content-Type: application/json" \
  -d '{
        "operations": [
          {
            "operation": "upsert",
            "request": {
              "key": "key1",
              "value": "myData"
            }
          },
          {
            "operation": "delete",
            "request": {
              "key": "key2"
            }
          }
        ],
        "metadata": {
          "partitionKey": "planet"
        }
      }'

Configuring state store for actors

Actors don’t support multiple state stores and require a transactional state store to be used with Dapr. View which services currently implement the transactional state store interface.

Specify which state store to be used for actors with a true value for the property actorStateStore in the metadata section of the statestore.yaml component file. For example, the following components yaml will configure Redis to be used as the state store for Actors.

apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: statestore
spec:
  type: state.redis
  version: v1
  metadata:
  - name: redisHost
    value: <redis host>
  - name: redisPassword
    value: ""
  - name: actorStateStore
    value: "true"

Optional behaviors

Key scheme

A Dapr-compatible state store shall use the following key scheme:

  • <App ID>||<state key> key format for general states
  • <App ID>||<Actor type>||<Actor id>||<state key> key format for Actor states.

Concurrency

Dapr uses Optimized Concurrency Control (OCC) with ETags. Dapr makes the following requirements optional on state stores:

  • A Dapr-compatible state store may support optimistic concurrency control using ETags. The store allows the update when an ETag:
    • Is associated with an save or delete request.
    • Matches the latest ETag in the database.
  • When ETag is missing in the write requests, the state store shall handle the requests in a last-write-wins fashion. This allows optimizations for high-throughput write scenarios, in which data contingency is low or has no negative effects.
  • A store shall always return ETags when returning states to callers.

Consistency

Dapr allows clients to attach a consistency hint to get, set, and delete operation. Dapr supports two consistency levels: strong and eventual.

Eventual Consistency

Dapr assumes data stores are eventually consistent by default. A state should:

  • For read requests, return data from any of the replicas.
  • For write requests, asynchronously replicate updates to configured quorum after acknowledging the update request.

Strong Consistency

When a strong consistency hint is attached, a state store should:

  • For read requests, return the most up-to-date data consistently across replicas.
  • For write/delete requests, synchronously replicate updated data to configured quorum before completing the write request.

Example: Complete options request example

The following is an example set request with a complete options definition:

curl -X POST http://localhost:3500/v1.0/state/starwars \
  -H "Content-Type: application/json" \
  -d '[
        {
          "key": "weapon",
          "value": "DeathStar",
          "etag": "xxxxx",
          "options": {
            "concurrency": "first-write",
            "consistency": "strong"
          }
        }
      ]'

Example: Working with ETags

The following is an example walk-through of an ETag usage when setting/deleting an object in a compatible state store. This sample defines Redis as statestore.

  1. Store an object in a state store:

    curl -X POST http://localhost:3500/v1.0/state/statestore \
        -H "Content-Type: application/json" \
        -d '[
                {
                    "key": "sampleData",
                    "value": "1"
                }
        ]'
    
  2. Get the object to find the ETag set automatically by the state store:

    curl http://localhost:3500/v1.0/state/statestore/sampleData -v
    * Connected to localhost (127.0.0.1) port 3500 (#0)
    > GET /v1.0/state/statestore/sampleData HTTP/1.1
    > Host: localhost:3500
    > User-Agent: curl/7.64.1
    > Accept: */*
    >
    < HTTP/1.1 200 OK
    < Server: fasthttp
    < Date: Sun, 14 Feb 2021 04:51:50 GMT
    < Content-Type: application/json
    < Content-Length: 3
    < Etag: 1
    < Traceparent: 00-3452582897d134dc9793a244025256b1-b58d8d773e4d661d-01
    <
    * Connection #0 to host localhost left intact
    "1"* Closing connection 0
    

    The returned ETag above was 1. If you send a new request to update or delete the data with the wrong ETag, it will return an error. Omitting the ETag will allow the request.

    # Update
    curl -X POST http://localhost:3500/v1.0/state/statestore \
        -H "Content-Type: application/json" \
        -d '[
                {
                    "key": "sampleData",
                    "value": "2",
                    "etag": "2"
                }
        ]'
    {"errorCode":"ERR_STATE_SAVE","message":"failed saving state in state store statestore: possible etag mismatch. error from state store: ERR Error running script (call to f_83e03ec05d6a3b6fb48483accf5e594597b6058f): @user_script:1: user_script:1: failed to set key nodeapp||sampleData"}
    
    # Delete
    curl -X DELETE -H 'If-Match: 5' http://localhost:3500/v1.0/state/statestore/sampleData
    {"errorCode":"ERR_STATE_DELETE","message":"failed deleting state with key sampleData: possible etag mismatch. error from state store: ERR Error running script (call to f_9b5da7354cb61e2ca9faff50f6c43b81c73c0b94): @user_script:1: user_script:1: failed to delete node
    app||sampleData"}
    
  3. Update or delete the object by simply matching the ETag in either the request body (update) or the If-Match header (delete). When the state is updated, it receives a new ETag that future updates or deletes will need to use.

    # Update
    curl -X POST http://localhost:3500/v1.0/state/statestore \
        -H "Content-Type: application/json" \
        -d '[
            {
                "key": "sampleData",
                "value": "2",
                "etag": "1"
            }
        ]'
    
    # Delete
    curl -X DELETE -H 'If-Match: 1' http://localhost:3500/v1.0/state/statestore/sampleData
    

Next Steps