Redis Storage

Spin provides an interface for you to read and write the Redis key/value store, and to publish Redis pub-sub messages.

Why do I need a Spin interface? Why can't I just use my language's Redis library?

The current version of the WebAssembly System Interface (WASI) doesn’t provide a sockets interface, so Redis libraries that depend on sockets can’t be built to Wasm. The Spin interface means Wasm modules can bypass this limitation by asking Spin to make the Redis connection on their behalf.

Using Redis From Applications

The Spin SDK surfaces the Spin Redis interface to your language. The set of operations is common across all SDKs:

OperationParametersReturnsBehavior
openaddressconnection resourceOpens a connection to the specified Redis instance. The host must be listed in allowed_outbound_hosts. Other operations must be called through a connection. (Exception: for JavaScript, do not call open, and pass the address to each data operation - see the language guides below.)
Single value operations
getkeybytesReturns the value of key. If the key does not exist, returns a zero-length array.
setkey, bytes-Sets the value of key, overwriting any existing value.
incrkeyintegerIncrements the value at key by 1. If the key does not exist, its value is set to 0 first (and immediately incremented to 1). If the current value isn’t an integer, or a string that represents an integer, it errors and the value is not changed.
dellist of keys-Removes the specified keys. Keys that don’t exist are ignored (they do not cause an error).
Set value operations
saddkey, list of stringsintegerAdds the strings to the set of values of key, and returns the number of newly added values. If the key does not exist, its value is set to the set of values
smemberskeylist of stringsReturns the set of values of key. if the key does not exist, this is an empty set.
sremkey, list of stringsintegerRemoves the strings from the set of values of key, and returns the number of newly removed values. If the key does not exist, this does nothing.
Pub-sub operations
publishchannel, bytes-Publishes a message to the specified channel, with the specified payload bytes.
General operations
executecommand, list of argument valueslist of resultsExecutes the specified command with the specified arguments. This is a general-purpose ‘escape hatch’ if you need a command that isn’t covered by the built-in operations.

The exact detail of calling these operations from your application depends on your language:

Want to go straight to the reference documentation? Find it here.

Redis functions are available in the spin_sdk::redis module.

To access a Redis instance, use the Connection::open function.

let connection = spin_sdk::redis::Connection::open(&address)?;

You can then call functions on the Connection to work with the Redis instance:

connection.set("my-key", &"my-value".into());
let data = connection.get("my-key")?;

For full details of the Redis API, see the Spin SDK reference documentation;

General Notes

  • Keys are of type &str.
  • Bytes parameters are of type &[u8] and return values are Vec<u8>.
  • Numeric return values are of type i64.
  • All functions wrap the return in anyhow::Result.

get Operation

  • This returns a Result<Option<Vec<u8>>>. If the key is not found, the return value is Ok(None).

del Operation

  • The list of keys is passed as &[String].

Set Operations

  • List arguments are passed as &[String] and returned as Vec<String>.

execute Operation

  • The arguments and results are enums, representing integers, binary payloads, and (for results) status and nil values.

You can find a complete Rust code example for using outbound Redis from an HTTP component in the Spin repository on GitHub. Please also see this, related, outbound Redis (using Rust) section.

Want to go straight to the reference documentation? Find it here.

Redis functions are available on the Redis object. The function names match the operations above, but you must pass the Redis instance address to each operation as its first parameter. For example:

import {Redis} from "@fermyon/spin-sdk"

const value = Redis.get(address, key);

General Notes

  • The spinSdk object is always available at runtime. Code checking and completion are available in TypeScript at design time if the module imports anything from the @fermyon/spin-sdk package.
  • Address and key parameters are strings.
  • Bytes parameters and return values are buffers (TypeScript ArrayBuffer).
  • Lists are passed and returned as arrays.
  • If a Spin SDK function fails, it throws an Error.

execute Operation

  • The arguments and results can be either numbers or buffers. (In TypeScript they are union types, e.g. BigInt | ArrayBuffer.)

You can find a complete TypeScript example for using outbound Redis from an HTTP component in the JavaScript SDK repository on GitHub. Please also see this, related, outbound Redis (using TypeScript) section.

Want to go straight to the reference documentation? Find it here.

Redis functions are available in the redis module. The function names are prefixed redis_. You must pass the Redis instance address to each operation as its first parameter. For example:

from spin_sdk import redis
with redis.open("redis://localhost:6379") as db:
    val = db.get("test")

General Notes

  • Address and key parameters are strings (str).
  • Bytes parameters and return values are bytes. (You can pass literal strings using the b prefix, e.g. redis_set(address, key, b"hello").)
  • Numeric return values are of type int64.
  • Lists are passed and returned as Python lists.
  • Errors are signalled through exceptions.

You can find a complete Python code example for using outbound Redis from an HTTP component in the Python SDK repository on GitHub. Please also see this, related, outbound Redis (using Python) section.

Want to go straight to the reference documentation? Find it here.

Redis functions are available in the github.com/fermyon/spin/sdk/go/v2/redis package. See Go Packages for reference documentation. The function names are TitleCased. For example:

import (
	"github.com/fermyon/spin/sdk/go/v2/redis"
)

rdb := redis.NewClient(addr)
payload, err := rdb.Get(key)

General Notes

  • Key parameters are strings.
  • Bytes parameters are byte slices ([]byte).
  • Lists are passed as slices. For example, redis.Del takes the keys to delete as a []string.
  • Errors are return through the usual Go multiple return values mechanism.

execute Operation

  • The arguments are passed as []redis.RedisParameter. You can construct RedisParameter instances around an interface{} but must provide a Kind. For example, hello := redis.RedisParameter{Kind: redis.RedisParameterKindBinary, Val: []byte("hello")}.
  • The results are returned as []redis.Result. You can use the Kind member of redis.Result to interpret the Val.

You can find a complete TinyGo example for using outbound Redis from an HTTP component in the Spin repository on GitHub. Please also see this, related, outbound Redis (using TinyGo) section.

Granting Network Permissions to Components

By default, Spin components are not allowed to make outgoing network requests, including Redis. This follows the general Wasm rule that modules must be explicitly granted capabilities, which is important to sandboxing. To grant a component permission to make network requests to a particular host, use the allowed_outbound_hosts field in the component manifest, specifying the host and allowed port:

[component.uses-redis]
allowed_outbound_hosts = ["redis://redis.example.com:6379"]

Configuration-Based Permissions

You can use application variables in the allowed_outbound_hosts field. However, this feature is not yet available on Fermyon Cloud.