---
title: "Create"
description: "Learn how to create and update Aerospike records using the Rust client's put() method, bins, and write policies."
---

# Create

> For the complete documentation index see: [llms.txt](https://aerospike.com/docs/llms.txt)
> 
> All documentation pages available in markdown.

The Aerospike Rust client’s `put()` method writes records to the database. Note that if they do not already exist, the set and bins are automatically created. You don’t have to define a schema for the database.

The following examples adds a bin `mybin` in the record `mykey` with a string value `myvalue`. This example uses the namespace `test`, which is the default namespace specified in the server configuration file. The following write policy specifies the re-transmission policy, timeout interval, record expiration, and what to do if the record already exists.

The examples demonstrate v2.0 of the client. v1.3 uses a slightly different interface, but is very similar.

```rust
let policy = WritePolicy::default();

policy.base().total_timeout = 50;  // 50 millisecond timeout.
```

> 📖 **API reference**: [`WritePolicy::default`](https://docs.rs/aerospike/latest/aerospike/struct.WritePolicy.html)

## Writing single value

When writing records, you must identify the record in the database using a key.

The following example creates a key for the record to insert. The value used for the `key` is the string `mykey`, to be stored in the Namespace `test` in the set `myset`. You can use other data types, such as integer for `key`.

```rust
let key = as_key!("test", "myset", "mykey");

let bin = as_bin!("mybin", "myvalue");

match client.put(&policy, &key, &vec![&bin]).await {

    Ok(()) => println!("Record written"),

    Err(err) => println!("Error writing record: {}", err),

}
```

> 📖 **API reference**: [`Client::put`](https://docs.rs/aerospike/latest/aerospike/struct.Client.html#method.put)

Observe that we pass the bin inside a vector, even if there is only one.

## Writing multiple values

To update multiple bins in a record, create additional bins and add them to the `put()` call:

```rust
// Write multiple values.

let bin1 = as_bin!("name", "John");

let bin2 = as_bin!("age", 25);

match client.put(&policy, &key, &vec![&bin1, &bin2]).await {

    Ok(()) => println!("All records written"),

    Err(err) => println!("Error writing records: {}", err),

};
```

> 📖 **API reference**: [`Client::put`](https://docs.rs/aerospike/latest/aerospike/struct.Client.html#method.put)

## Deleting a bin

To delete a bin, set the bin value to the empty value:

```rust
// Delete the "age" bin by writing a nil value.

let bin1 = as_bin!("age");

match client.put(&policy, &key, &vec![&bin1]).await {

    Ok(()) => println!("Bin 'age' deleted"),

    Err(err) => println!("Error deleting bin: {}", err),

};
```

> 📖 **API reference**: [`Client::put`](https://docs.rs/aerospike/latest/aerospike/struct.Client.html#method.put)

## Modifying write behavior

The default behavior of a `put()` operation is:

-   Create the record (if it doesn’t exist) in the cluster.
-   Add the bins if they do not exist.
-   Update bin values in the record (if the bins already exist).
-   If the record has other bins, keep them in the record.

Use the `WritePolicy` to change write behavior. Some policy changes are:

-   Only write if the record does not already exist:
    -   Set `policy.record_exists_action` to `RecordExistsAction::CreateOnly`.
-   Completely replace a record _ONLY_ if it exists:
    -   Set `policy.record_exists_action` to `RecordExistsAction::ReplaceOnly`

## Writing record with time-to-live (TTL)

This example specifies a time-to-live value for a record on a write, setting the record expiration to two seconds:

```rust
let policy = WritePolicy::default();

policy.expiration = Expiration::Seconds(2);

match client.put(&policy, &key, &bins).await {

    Ok(()) => println!("All records written"),

    Err(err) => println!("Error writing records: {}", err),

};
```

> 📖 **API reference**: [`WritePolicy::default`](https://docs.rs/aerospike/latest/aerospike/struct.WritePolicy.html) | [`Expiration`](https://docs.rs/aerospike/latest/aerospike/enum.Expiration.html) | [`Client::put`](https://docs.rs/aerospike/latest/aerospike/struct.Client.html#method.put)

Setting `policy.expiration` to certain specific values may have desirable side-effects, depending on your application.

| policy.expiration value | effect |
| --- | --- |
| `Expiration::NamespaceDefault` | applies the default TTL on the server side each time a record updates. |
| `Expiration::Never` | specifies that the record never expires. |
| `Expiration::DontUpdate` | requests the server to update a record without changing it’s TTL. (Requires Aerospike Server version 3.10.1 or later.) |

If left unchanged from creation, the `policy.expiration` value defaults to `Expiration::NamespaceDefault`.

::: note
Setting per-record TTLs with `Expiration::Seconds` requires Aerospike Enterprise Edition. Community Edition returns a `FailForbidden` error. To run the examples on CE, omit the `expiration` setting or use `Expiration::NamespaceDefault`.
:::

## Read-modify-write

Record Read-Modify-Write (or Check-and-Set) involves:

-   Reading the record, and remembering its generation value for later.
-   Modifying the record at the application level.
-   Setting `policy.generation_policy` to `GenerationPolicy::ExpectGenEqual` while setting `policy.generation` to the previously set generation value.

This implements a form of optimistic locking; should the write operation fail, check for a generation error; if this error occurred, you know that the record was updated by another thread. This gives you the opportunity to retry the operation in the event of a collision. This is similar to [load-linked/store-conditional](https://en.wikipedia.org/wiki/Load-link/store-conditional) optimistic mutual exclusion.

## Complete example

The following complete program connects to Aerospike on `localhost:3000`, writes two records with `name` and `age` bins, applies a TTL of 10 seconds, and then closes the client connection.

```rust
use aerospike::{as_bin, as_key, Client, ClientPolicy, Error, Expiration, WritePolicy};

#[tokio::main]

async fn main() -> Result<(), Error> {

    // Connect to Aerospike running on localhost.

    let client_policy = ClientPolicy::default();

    let client = Client::new(&client_policy, &"127.0.0.1:3000").await?;

    // Create records with bins name + age and a TTL of 10 seconds.

    let mut write_policy = WritePolicy::default();

    write_policy.expiration = Expiration::Seconds(10);

    let records = [("user-1", "Alice", 29), ("user-2", "Bob", 34)];

    for (user_key, name, age) in records {

        let key = as_key!("test", "users", user_key);

        let bins = [as_bin!("name", name), as_bin!("age", age)];

        client.put(&write_policy, &key, &bins).await?;

        println!("Created record: key={user_key}, name={name}, age={age}, ttl=10s");

    }

    // Close the connection.

    client.close().await?;

    println!("Connection closed");

    Ok(())

}
```

> 📖 **API reference**: [`Client::new`](https://docs.rs/aerospike/latest/aerospike/struct.Client.html#method.new) | [`WritePolicy::default`](https://docs.rs/aerospike/latest/aerospike/struct.WritePolicy.html#method.default) | [`Expiration::Seconds`](https://docs.rs/aerospike/latest/aerospike/enum.Expiration.html#variant.Seconds) | [`as_key!`](https://docs.rs/aerospike/latest/aerospike/macro.as_key.html) | [`as_bin!`](https://docs.rs/aerospike/latest/aerospike/macro.as_bin.html) | [`Client::put`](https://docs.rs/aerospike/latest/aerospike/struct.Client.html#method.put) | [`Client::close`](https://docs.rs/aerospike/latest/aerospike/struct.Client.html#method.close)

### Expected results

When the Aerospike server is running and reachable on `127.0.0.1:3000`, output is similar to:

```text
Created record: key=user-1, name=Alice, age=29, ttl=10s

Created record: key=user-2, name=Bob, age=34, ttl=10s

Connection closed
```