Please contact us if you need access to this feature.

Stash is a key-value store that you can use to power your B2B integration or EDI workflow. Use it to track documents processed, increment control numbers, or reference lookup tables, all using a simple API. There are no servers, clusters, networking, or replication to manage.

What can Stash be used for?

Stash allows you to store values associated with keys, and later retrieve those values using the same keys. It can be used as a standalone data store for a wide variety of general use cases, or as part of an EDI workflow built on Stedi.

Common use cases for Stash include:

  • Complete an end-to-end EDI integration after you have configured Stedi for a new trading partner. For example, you can use Stash to configure where you want to send processed data.
  • Extend an EDI integration. For example, you might want to store information extracted from documents or APIs for later use, such as inventory or price catalogs.
  • Store large mapping tables – for example, a directory with millions of entries that map vendor SKUs to internal SKUs.

How does Stash work?

Stash allows you to create Keyspaces that can store and allow you to retrieve any number of key-value pairs. Stash automatically scales up or down your Keyspace throughput capacity, with no performance degradation. All Stash data is encrypted at rest and in transit, which eliminates the operational burden and complexity involved in protecting sensitive data. Stash is also architected to ensure high availability and data durability.

Stash is intentionally built with a minimal feature set. The fundamental concepts in Stash are keyspaceskeys and values. Key-value pairs are always scoped to a named keyspace, and all operations on keys and values must include the name of the keyspace. Keyspace names are unique in a Stedi account, and can only be reused once the keyspace has been deleted. Key-value pairs can be a maximum of 8 KB in size.

A keyspace can hold an unlimited amount of data, and system performance improves as a keyspace is accessed more often. We recommend minimizing the number of keyspaces used (the default per-account limit is 10, though that can be raised upon request), and only creating additional keyspaces when building multiple applications inside of one account, or when different teams each need to manage their own data. In order to avoid key conflicts when using the same keyspace for different use cases within a single application, we recommend prepending keys with a type identification or sub-application identifier.

Stash’s interface is flexible and easy to use, with just a handful of API operations:

  • Create keyspace. Create a keyspace in which to store key-value pairs.
  • Get keyspace. See information about a keyspace.
  • Delete keyspace. Remove a keyspace.
  • List keyspaces. List of your existing keyspaces.
  • Set value. Add or update a key-value pair.
  • Get value. Retrieve the current value of a given key.
  • Delete value. Remove a key-value pair from a keyspace.
  • List values. Retrieve a list of key-value pairs from a keyspace.

A stash value can be a valid JSON value of type:

  • string
  • number
  • boolean
  • array
  • object

Read consistency

All read (GetValue, ListValues) operations are strongly consistent. Reads always return the most up-to-date data, reflecting the updates from all prior write (SetValue, DeleteValue) operations that were successful.

Ordering

For the ListValues operation, there is no guarantee on the order of results returned.

Endpoints

EnvironmentEndpoint
Globalhttps://stash.us.stedi.com/2022-04-20

cURL/Postman example

This example highlights the common operations for the Stash service using curl. These examples can also easily be imported into Postman.

Authentication

Ensure that you have created a Stedi API Key. If using curl, you can export this API key in the STEDI_API_KEY environment variable. If using Postman, the API key can be configured under the “Authorization” header with Type set to API Key, Key set to Authorization and Value set to Key <your-stedi-api-key>.

Creating a Keyspace

In order to store keys and values, we need to create a Keyspace. We may use a single Keyspace for different situations, as long as we ensure that the keys will not overwrite one another.

curl --request POST 'https://stash.us.stedi.com/2022-04-20/CreateKeyspace' \
    --header "Authorization: ${STEDI_API_KEY}" \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "keyspaceName": "my-keyspace"
    }'

Note: It may take a few seconds for a Keyspace to be ready to use. You can use the /GetKeyspace operation to determine if it is in the ACTIVE state.

Storing Values

This snippet just stores a simple item where the Key is foo and the Value is bar. Note how we use the same Keyspace name as used in the previous step.

curl --request POST 'https://stash.us.stedi.com/2022-04-20/SetValue' \
    --header "Authorization: ${STEDI_API_KEY}" \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "keyspaceName": "my-keyspace",
        "key": "foo",
        "value": "bar"
    }'

Retrieving Values

Simply use the GetValue operation to retrieve any values.

curl --request POST 'https://stash.us.stedi.com/2022-04-20/GetValue' \
    --header "Authorization: ${STEDI_API_KEY}" \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "keyspaceName": "my-keyspace",
        "key": "foo"
    }'

Atomically increment a number

The IncrementValue operation will atomically increment a number by the amount specified. If the key does not exist, it will be initialized with 0. If the key exists and is not a number, this results in a ValidationError error.

curl --request POST 'https://stash.us.stedi.com/2022-04-20/IncrementValue' \
    --header "Authorization: ${STEDI_API_KEY}" \
    --header 'Content-Type: application/json' \
    --data-raw '{
        "keyspaceName": "my-keyspace",
        "key": "increasing-number",
        "amount": 1
    }'

JavaScript example

This example highlights the common operations for the Stash service using the Stedi SDK for JavaScript.

Setup

Install the SDK with npm install -g @stedi/sdk-client-stash. Ensure you have created a Stedi API Key.

const { StashClient } = require('@stedi/sdk-client-stash');

const client = new StashClient({
  region: 'us',
  apiKey: '<replace with Stedi API key>',
});

Creating a Keyspace

In order to store keys and values, we need to create a Keyspace. We may use a single Keyspace for different situations, as long as we ensure that the keys will not overwrite one another.

const { CreateKeyspaceCommand } = require('@stedi/sdk-client-stash');

try {
  const output = await client.send(
    new CreateKeyspaceCommand({
      keyspaceName: 'my-keyspace',
    }),
  );
  console.log(`Keyspace status is ${output.status}`);
} catch (e) {
  throw e;
}

Note: It may take a few seconds for a Keyspace to be ready to use. You can use the GetKeyspace operation to determine if it is in the ACTIVE state.

Storing Values

This snippet just stores a simple item where the Key is foo and the Value is bar. Note how we use the same Keyspace name as used in the previous step.

const { SetValueCommand } = require("@stedi/sdk-client-stash");

  const rl = readline.createInterface({
    input: fileStream,
    crlfDelay: Infinity,
  });

  for await (const line of rl) {
    item = JSON.parse(line);
    const url = baseUrl + "/SetValue";
    const payload = {
      keyspace: keyspaceName,
      key: `${item.vendor_id}|${item.vendor_sku}`,
      value: item.internal_sku,
    };
    await axios
      .post(url, payload, config)
      .then((resp) => {
        console.log(`Stored key=${payload.key}, value=${payload.value}`);
      })
      .catch((e) => {
        console.log(`Error setting value: ${e}`);
        process.exit(1);
      });
  }
}

Retrieving Values

Simply use the GetValue operation to retrieve any values.

const { GetValueCommand } = require('@stedi/sdk-client-stash');

try {
  const output = await client.send(
    new GetValueCommand({
      keyspaceName: 'my-keyspace',
      key: 'foo',
    }),
  );
  console.log(`Retrieved key=${output.key}, value=${output.value}`);
} catch (e) {
  console.error(e);
}

Incrementing Numbers

The IncrementValue operation will atomically increment a number by the amount specified. If the key does not exist, it will be initialized with 0. If the key exists and is not a number, this results in a ValidationError error.

const { IncrementValueCommand } = require('@stedi/sdk-client-stash');

try {
  const output = await client.send(
    new IncrementValueCommand({
      keyspaceName: 'my-keyspace',
      key: 'invoice-number',
      amount: 1,
    }),
  );
  console.log(`Incremented key=${output.key}, value=${output.value}`);
} catch (e) {
  console.error(e);
}

Limits

Unless noted otherwise, limits can be increased upon request. To request a limit increase, contact support.

Keyspaces

Limits for Keyspaces, which can contain many Key-Value Pairs

Resource or operationDefault limitCan be increased
Maximum number of Keyspaces10Yes
Keyspace sizeNo practical limit in terms of bytes or Key-Value PairsN/A
Throttle per account, across all Stash APIs25 requests per second (RPS)Yes
Keyspace Name length250 charactersNo
Keyspace Name allowed charactersAlphanumeric (a-zA-Z0-9), underscore (_), period (.), hyphen (-)No

Key-Value Pairs

Limits for Key-Value Pairs, which are made up of Keys and Values

Resource or operationDefault limitCan be increased
Key length255 charactersNo
Key-Value Pair size8 KB (more details)No
Precision of Number types in Values38 significant figures (more details)No
Supported string characters in ValuesUTF-8No

Size of a Key-Value Pair

  • The size of a Key-Value Pair is equal to: i) the number of characters in the Key, plus ii) the Value size, plus iii) 2 additional bytes of overhead.
  • The Value size is equal to: i) the number of bytes in the JSON attribute names (encoded with UTF-8 binary encoding), plus ii) the sizes of the JSON values.

You can estimate the size of JSON values with the following guidelines:

  • String values are encoded with UTF-8 binary encoding. The size of a string is the number of UTF-8-encoded bytes.
  • Number values are variable length, with up to 38 significant digits. Leading and trailing zeroes are trimmed. The size of a number value is approximately 1 byte per two significant digits + 1 byte.
  • Boolean or Null values are 1 byte in size.
  • Lists incur 3 bytes of overhead, regardless of their contents. The size of a List value is the sum of the size of its elements + 1 byte per element. The size of an empty List is just the 3 bytes of overhead.
  • Maps incur 3 bytes of overhead, regardless of their contents. The size of a Map value is the sum of the size of its string keys + the sum of the size of its elements + 1 byte per element. The size of an empty Map is just the 3 bytes of overhead.

For storage billing purposes, each Stash value requires 100 bytes of overhead for indexing.

Accepted range for Numeric values

Numbers can have up to 38 significant figures.

  • Positive range: 1E-130 to 9.9999999999999999999999999999999999999E+125
  • Negative range: -9.9999999999999999999999999999999999999E+125 to -1E-130