# Delete records

Learn how to delete records from Aerospike using the Developer SDK. This guide covers simple deletion, conditional deletes, and handling deletion of non-existent records.

## Delete a record

Use `delete()` to remove a record by its key:

-   [Java](#tab-panel-3108)
-   [Python](#tab-panel-3109)

```java
DataSet users = DataSet.of("test", "users");

session.delete(users.id("user-1"))

    .execute();
```

```python
async def demo(session):

    users = DataSet.of("test", "users")

    await session.delete(key=users.id("user-1")).execute()
```

## Check if delete succeeded

Use the delete result row to determine whether a record was actually deleted:

-   [Java](#tab-panel-3110)
-   [Python](#tab-panel-3111)

```java
import com.aerospike.client.sdk.RecordResult;

import com.aerospike.client.sdk.RecordStream;

RecordStream deleteStream = session.delete(users.id("user-1")).execute();

boolean deleted = deleteStream.getFirst().map(RecordResult::asBoolean).orElse(false);

if (deleted) {

    System.out.println("Record deleted successfully");

} else {

    System.out.println("Record didn't exist");

}
```

```python
async def demo(session):

    users = DataSet.of("test", "users")

    stream = await session.delete(key=users.id("user-1")).execute()

    row = await stream.first()

    deleted = row.as_bool() if row is not None else False

    stream.close()

    if deleted:

        print("Record deleted successfully")

    else:

        print("Record didn't exist")
```

## Conditional delete (generation check)

Delete only if the record hasn’t been modified since you last read it:

-   [Java](#tab-panel-3112)
-   [Python](#tab-panel-3113)

```java
import com.aerospike.client.sdk.AerospikeException;

import com.aerospike.client.sdk.Record;

import com.aerospike.client.sdk.RecordResult;

import com.aerospike.client.sdk.RecordStream;

// Read the record first

RecordStream readStream = session.query(users.id("user-1")).execute();

Record user = readStream.getFirstRecord();

// Delete only if generation matches

try {

    session.delete(users.id("user-1"))

        .ensureGenerationIs(user.generation)

        .execute();

    System.out.println("Deleted successfully");

} catch (GenerationException e) {

    System.out.println("Record was modified, delete aborted");

}
```

```python
from aerospike_sdk import GenerationError

async def demo(session):

    users = DataSet.of("test", "users")

    # Read the record first

    stream = await session.query(users.id("user-1")).execute()

    row = await stream.first_or_raise()

    user = row.record_or_raise()

    stream.close()

    # Delete only if generation matches

    try:

        await (

            session.delete(key=users.id("user-1"))

            .ensure_generation_is(user.generation)

            .execute()

        )

        print("Deleted successfully")

    except GenerationError:

        print("Record was modified, delete aborted")
```

::: use case
Generation-based conditional delete is useful when you want to ensure you’re deleting the exact version of the record you read, preventing accidental deletion of updated data.
:::

## Delete only if exists

By default, deleting a non-existent record is a no-op. In Java, use `exists()` first if you need a hard failure when the record is missing. In Python, check existence first and then delete:

-   [Java](#tab-panel-3114)
-   [Python](#tab-panel-3115)

```java
// There is no deleteOnly() in the Java SDK; check existence first if you must fail when absent.

boolean existed = session.exists(users.id("user-1")).execute().getFirstBoolean().orElse(false);

if (!existed) {

    System.out.println("Record not found");

} else {

    session.delete(users.id("user-1")).execute().close();

    System.out.println("Record deleted");

}
```

```python
async def demo(session):

    users = DataSet.of("test", "users")

    stream = await session.exists(users.id("user-1")).execute()

    row = await stream.first()

    stream.close()

    if row is None or not row.as_bool():

        print("Record not found")

        return

    await session.delete(key=users.id("user-1")).execute()

    print("Record deleted")
```

## Delete with durability options

For critical deletes, ensure durability. These can either be done on a per-call basis, or set on the session level via a Behavior.

-   [Java](#tab-panel-3116)
-   [Python](#tab-panel-3117)

```java
// Use a durable session for important deletes

session.delete(users.id("important-record"))

    .withDurableDelete()

    .execute();
```

```python
# Use a durable session for important deletes

session.delete(users.id("important-record")).durably_delete().execute()
```

> 📖 **Learn more**: [Behaviors](https://aerospike.com/docs/develop/client/sdk/concepts/behaviors) explains durability options.

## Batch delete

For deleting multiple records efficiently, see [Batch Operations](https://aerospike.com/docs/develop/client/sdk/usage/batch).

-   [Java](#tab-panel-3118)
-   [Python](#tab-panel-3119)

```java
// Quick preview - see Batch Operations for full details

RecordStream deleteStream = session.delete(users.ids("user-1", "user-2", "user-3")).execute();
```

```python
# Quick preview - see Batch Operations for full details

await (

    session.batch()

    .delete(users.id("user-1"))

    .delete(users.id("user-2"))

    .delete(users.id("user-3"))

    .execute()

)
```

## Soft delete pattern

Instead of permanently deleting, mark records as deleted:

-   [Java](#tab-panel-3120)
-   [Python](#tab-panel-3121)

```java
import com.aerospike.client.sdk.Record;

import com.aerospike.client.sdk.RecordResult;

import com.aerospike.client.sdk.RecordStream;

import java.util.ArrayList;

import java.util.List;

// Soft delete: mark as deleted instead of removing

session.update(users.id("user-1"))

    .bin("deleted").setTo(true)

    .bin("deleted_at").setTo(System.currentTimeMillis())

    .execute();

// When querying, filter out deleted records

RecordStream stream = session.query(users)

    .where("$.deleted == false")

    .execute();

List<Record> activeUsers = stream.stream().asList();

}

stream.close();
```

```python
import time

async def demo(session):

    users = DataSet.of("test", "users")

    # Soft delete: mark as deleted instead of removing

    await (

        session.update(users.id("user-1"))

        .bin("deleted").set_to(True)

        .bin("deleted_at").set_to(time.time())

        .execute()

    )

    # When querying, filter out deleted records

    stream = await session.query(users).where("$.deleted == false").execute()

    active_users = []

    async for row in stream:

        active_users.append(row.record_or_raise())

    stream.close()
```

## Delete with TTL (auto-expire)

Instead of explicit deletion, let records expire automatically. Note: do not decrease the expiration time on a record.

-   [Java](#tab-panel-3122)
-   [Python](#tab-panel-3123)

```java
import java.time.Duration;

// Set TTL to expire in 1 minute (deferred delete)

session.touch(users.id("user-1"))

    .expireRecordAfter(Duration.ofMinutes(1))

    .execute();
```

```python
# Set TTL to expire in 1 minute (deferred delete)

await (

    session.touch(users.id("user-1"))

    .expire_record_after_seconds(60)

    .execute()

)
```

## Complete example

-   [Java](#tab-panel-3124)
-   [Python](#tab-panel-3125)

```java
import com.aerospike.client.sdk.Cluster;

import com.aerospike.client.sdk.ClusterDefinition;

import com.aerospike.client.sdk.DataSet;

import com.aerospike.client.sdk.Record;

import com.aerospike.client.sdk.RecordResult;

import com.aerospike.client.sdk.RecordStream;

import com.aerospike.client.sdk.Session;

import com.aerospike.client.sdk.policy.Behavior;

public class DeleteRecordsExample {

    public static void main(String[] args) {

        try (Cluster cluster = new ClusterDefinition("localhost", 3000).connect()) {

            Session session = cluster.createSession(Behavior.DEFAULT);

            DataSet users = DataSet.of("test", "users");

            String deleteKey = "delete-example-user";

            String conditionalKey = "delete-example-conditional";

            // Cleanup so the example is repeatable.

            session.delete(users.id(deleteKey)).execute().close();

            session.delete(users.id(conditionalKey)).execute().close();

            // Create a test record

            session.insert(users)

                .bins("name")

                .id(deleteKey).values("Test User")

                .execute();

            // Simple delete

            RecordStream deletedStream = session.delete(users.id(deleteKey)).execute();

            boolean deleted = deletedStream.getFirst().map(RecordResult::asBoolean).orElse(false);

            System.out.println("Deleted: " + deleted);

            // Try to delete again (returns false)

            RecordStream secondDeletedStream = session.delete(users.id(deleteKey)).execute();

            deleted = secondDeletedStream.getFirst().map(RecordResult::asBoolean).orElse(false);

            secondDeletedStream.close();

            System.out.println("Second delete: " + deleted);

            // Conditional delete example

            session.insert(users)

                .bins("name")

                .id(conditionalKey).values("Conditional User")

                .execute();

            RecordStream rs = session.query(users.id(conditionalKey)).execute();

            Record record = rs.getFirstRecord();

            session.delete(users.id(conditionalKey))

                .ensureGenerationIs(record.generation)

                .execute();

            System.out.println("Conditional delete succeeded");

        }

    }

}
```

```python
import asyncio

from aerospike_sdk import Behavior, DataSet, Client

async def main():

    async with Client("localhost:3000") as client:

        session = client.create_session(Behavior.DEFAULT)

        users = DataSet.of("test", "users")

        delete_key = users.id("delete-example-user")

        conditional_key = users.id("delete-example-conditional")

        # Cleanup so the example is repeatable.

        stream = await session.delete(key=delete_key).execute()

        stream.close()

        stream = await session.delete(key=conditional_key).execute()

        stream.close()

        # Create a test record

        await session.insert(key=delete_key).put(

            {"name": "Test User"}

        ).execute()

        # Simple delete

        stream = await session.delete(key=delete_key).execute()

        row = await stream.first()

        deleted = row.as_bool() if row is not None else False

        stream.close()

        print(f"Deleted: {deleted}")

        # Try to delete again (returns False)

        stream = await session.delete(key=delete_key).execute()

        row = await stream.first()

        deleted = row.as_bool() if row is not None else False

        stream.close()

        print(f"Second delete: {deleted}")

        # Conditional delete example

        await session.insert(key=conditional_key).put(

            {"name": "Conditional User"}

        ).execute()

        stream = await session.query(conditional_key).execute()

        row = await stream.first_or_raise()

        record = row.record_or_raise()

        stream.close()

        await (

            session.delete(key=conditional_key)

            .ensure_generation_is(record.generation)

            .execute()

        )

        print("Conditional delete succeeded")

if __name__ == "__main__":

    asyncio.run(main())
```

## API reference summary

| Method | Description | Link |
| --- | --- | --- |
| `delete()` | Delete a record by key | Java · Python |
| `.ensureGenerationIs(gen)` / `.ensure_generation_is(gen)` | Conditional delete | — |
| (No `deleteOnly` / `delete_only` in either SDK) | Use `exists()` then `delete()`, or inspect the delete result | — |

## Next steps

Batch Operations

Delete multiple records efficiently.

[Batch Operations →](https://aerospike.com/docs/develop/client/sdk/usage/batch)

Query Records

Find records to delete with DSL queries.

[Query Records →](https://aerospike.com/docs/develop/client/sdk/usage/query)

Error Handling

Handle deletion errors gracefully.

[Error Handling →](https://aerospike.com/docs/develop/client/sdk/concepts/errors)