Skip to main content
This guide covers the fundamental Create, Read, Update, and Delete (CRUD) operations in RocksDB.

Opening a Database

Before performing any operations, you need to open a RocksDB database:
#include "rocksdb/db.h"
#include "rocksdb/options.h"

using ROCKSDB_NAMESPACE::DB;
using ROCKSDB_NAMESPACE::Options;
using ROCKSDB_NAMESPACE::Status;

std::unique_ptr<DB> db;
Options options;

// Optimize RocksDB. This is the easiest way to get RocksDB to perform well
options.IncreaseParallelism();
options.OptimizeLevelStyleCompaction();

// Create the DB if it's not already present
options.create_if_missing = true;

// Open DB
Status s = DB::Open(options, "/path/to/db", &db);
assert(s.ok());
The IncreaseParallelism() and OptimizeLevelStyleCompaction() methods are the easiest way to get good performance from RocksDB. They set reasonable defaults for most workloads.

Write Operations

Put - Writing Key-Value Pairs

The Put operation writes or updates a key-value pair:
Status Put(const WriteOptions& options, const Slice& key, const Slice& value);
Example:
#include "rocksdb/slice.h"

using ROCKSDB_NAMESPACE::WriteOptions;

// Put key-value
Status s = db->Put(WriteOptions(), "key1", "value");
assert(s.ok());
If the key already exists, Put will overwrite the existing value.

Delete - Removing Keys

The Delete operation removes a key from the database:
Status Delete(const WriteOptions& options, const Slice& key);
Example:
Status s = db->Delete(WriteOptions(), "key1");
assert(s.ok());

Read Operations

Get - Reading Values

The Get operation retrieves the value associated with a key:
Status Get(const ReadOptions& options, const Slice& key, std::string* value);
Example:
using ROCKSDB_NAMESPACE::ReadOptions;

std::string value;
Status s = db->Get(ReadOptions(), "key1", &value);
if (s.ok()) {
    // Key found, value contains the data
    std::cout << "Value: " << value << std::endl;
} else if (s.IsNotFound()) {
    // Key doesn't exist
    std::cout << "Key not found" << std::endl;
} else {
    // Error occurred
    std::cerr << "Error: " << s.ToString() << std::endl;
}

Using PinnableSlice for Better Performance

For better performance, use PinnableSlice to avoid unnecessary memory copies:
using ROCKSDB_NAMESPACE::PinnableSlice;

PinnableSlice pinnable_val;
Status s = db->Get(ReadOptions(), db->DefaultColumnFamily(), "key2", &pinnable_val);
assert(s.ok());
assert(pinnable_val == "value");

// Reset PinnableSlice after each use and before each reuse
pinnable_val.Reset();
Always call Reset() on a PinnableSlice before reusing it. The Slice pointed by pinnable_val is not valid after calling Reset().

Atomic Batch Operations

RocksDB allows you to apply multiple operations atomically using WriteBatch:
using ROCKSDB_NAMESPACE::WriteBatch;

WriteBatch batch;
batch.Delete("key1");
batch.Put("key2", "value");

Status s = db->Write(WriteOptions(), &batch);
assert(s.ok());
After the batch is applied:
// key1 has been deleted
Status s = db->Get(ReadOptions(), "key1", &value);
assert(s.IsNotFound());

// key2 has the new value
s = db->Get(ReadOptions(), "key2", &value);
assert(s.ok());
assert(value == "value");
1

Create a WriteBatch

Instantiate a WriteBatch object to hold multiple operations.
2

Add operations

Add Put, Delete, or other operations to the batch.
3

Apply atomically

Call db->Write() to apply all operations atomically.

Error Handling

All RocksDB operations return a Status object that indicates success or failure:
Status s = db->Put(WriteOptions(), "key", "value");

if (s.ok()) {
    // Success
} else if (s.IsNotFound()) {
    // Key not found (for Get operations)
} else if (s.IsCorruption()) {
    // Data corruption detected
} else if (s.IsIOError()) {
    // I/O error occurred
} else {
    // Other error
    std::cerr << "Error: " << s.ToString() << std::endl;
}

Closing the Database

RocksDB databases are automatically closed when the DB object is destroyed:
// Automatic cleanup when unique_ptr goes out of scope
db.reset();

// Or simply let it go out of scope

Complete Example

Here’s a complete example demonstrating basic operations:
#include <cstdio>
#include <memory>
#include <string>

#include "rocksdb/db.h"
#include "rocksdb/options.h"
#include "rocksdb/slice.h"

using ROCKSDB_NAMESPACE::DB;
using ROCKSDB_NAMESPACE::Options;
using ROCKSDB_NAMESPACE::PinnableSlice;
using ROCKSDB_NAMESPACE::ReadOptions;
using ROCKSDB_NAMESPACE::Status;
using ROCKSDB_NAMESPACE::WriteBatch;
using ROCKSDB_NAMESPACE::WriteOptions;

int main() {
  std::unique_ptr<DB> db;
  Options options;
  
  // Optimize RocksDB. This is the easiest way to get RocksDB to perform well
  options.IncreaseParallelism();
  options.OptimizeLevelStyleCompaction();
  
  // create the DB if it's not already present
  options.create_if_missing = true;

  // open DB
  Status s = DB::Open(options, "/tmp/rocksdb_simple_example", &db);
  assert(s.ok());

  // Put key-value
  s = db->Put(WriteOptions(), "key1", "value");
  assert(s.ok());
  
  std::string value;
  // get value
  s = db->Get(ReadOptions(), "key1", &value);
  assert(s.ok());
  assert(value == "value");

  // atomically apply a set of updates
  {
    WriteBatch batch;
    batch.Delete("key1");
    batch.Put("key2", value);
    s = db->Write(WriteOptions(), &batch);
  }

  s = db->Get(ReadOptions(), "key1", &value);
  assert(s.IsNotFound());

  db->Get(ReadOptions(), "key2", &value);
  assert(value == "value");

  return 0;
}

Next Steps

Configuration

Learn how to configure RocksDB for your workload

Iterators

Learn how to scan and iterate through data

Transactions

Implement ACID transactions for your application

Merge Operators

Implement read-modify-write semantics efficiently

Build docs developers (and LLMs) love