Skip to main content

Overview

This guide will walk you through creating your first RocksDB application. You’ll learn how to open a database, perform basic operations, and understand core concepts.
This guide assumes you have already installed RocksDB on your system.

Your First RocksDB Program

Let’s build a simple program that demonstrates the basic CRUD operations in RocksDB.
1

Include Required Headers

Start by including the necessary RocksDB headers:
#include <cassert>
#include <memory>
#include <string>
#include "rocksdb/db.h"
#include "rocksdb/options.h"
#include "rocksdb/slice.h"
Import the RocksDB namespace:
using ROCKSDB_NAMESPACE::DB;
using ROCKSDB_NAMESPACE::Options;
using ROCKSDB_NAMESPACE::ReadOptions;
using ROCKSDB_NAMESPACE::Status;
using ROCKSDB_NAMESPACE::WriteBatch;
using ROCKSDB_NAMESPACE::WriteOptions;
2

Configure and Open the Database

Configure your database options and open it:
std::unique_ptr<DB> db;
Options options;

// Optimize RocksDB - easiest way to get good performance
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());
Performance Tip: IncreaseParallelism() sets the number of background threads to the number of CPU cores, and OptimizeLevelStyleCompaction() configures options optimized for level-style compaction.
3

Write Data (Put)

Store a key-value pair:
// Put key-value
s = db->Put(WriteOptions(), "key1", "value");
assert(s.ok());
The Put() method takes:
  • WriteOptions - Controls write behavior (sync, disable WAL, etc.)
  • key - The key as a string or Slice
  • value - The value to store
4

Read Data (Get)

Retrieve a value by key:
std::string value;
s = db->Get(ReadOptions(), "key1", &value);
assert(s.ok());
assert(value == "value");
The Get() method returns:
  • Status::OK() if the key exists
  • Status::NotFound() if the key doesn’t exist
  • Other error statuses for failures
5

Atomic Batch Operations

Apply multiple operations atomically using WriteBatch:
{
  WriteBatch batch;
  batch.Delete("key1");
  batch.Put("key2", value);
  s = db->Write(WriteOptions(), &batch);
}

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

// Verify key2 exists
db->Get(ReadOptions(), "key2", &value);
assert(value == "value");
All operations in a WriteBatch are applied atomically - either all succeed or all fail. This ensures data consistency.
6

Delete Data

Remove a key from the database:
s = db->Delete(WriteOptions(), "key2");
assert(s.ok());

Complete Example

Here’s the complete working example from the RocksDB source code:
examples/simple_example.cc
#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;

#if defined(OS_WIN)
std::string kDBPath = "C:\\Windows\\TEMP\\rocksdb_simple_example";
#else
std::string kDBPath = "/tmp/rocksdb_simple_example";
#endif

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, kDBPath, &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");

  db.reset();

  return 0;
}

Using PinnableSlice for Better Performance

For better performance, use PinnableSlice instead of std::string to avoid unnecessary memory copies:
PinnableSlice pinnable_val;
db->Get(ReadOptions(), db->DefaultColumnFamily(), "key2", &pinnable_val);
assert(pinnable_val == "value");
Performance Optimization: PinnableSlice can avoid a memcpy by directly pointing to RocksDB’s internal buffer when possible. Always call Reset() before reusing a PinnableSlice.

PinnableSlice with Fallback Buffer

std::string string_val;
// If it cannot pin the value, it copies the value to its internal buffer
PinnableSlice pinnable_val(&string_val);
db->Get(ReadOptions(), db->DefaultColumnFamily(), "key2", &pinnable_val);
assert(pinnable_val == "value");
// If the value is not pinned, the internal buffer must have the value
assert(pinnable_val.IsPinned() || string_val == "value");

Compiling Your Program

g++ -std=c++20 simple_example.cc -o simple_example \
  -lrocksdb -lpthread -lsnappy -lz -lbz2 -llz4 -lzstd
RocksDB requires C++20 support. Ensure you have GCC 11+ or Clang 10+ installed.

Understanding Status Objects

RocksDB uses Status objects to indicate success or failure:
Status s = db->Get(ReadOptions(), "key1", &value);

if (s.ok()) {
  // Success - key found
  std::cout << "Value: " << value << std::endl;
} else if (s.IsNotFound()) {
  // Key doesn't exist
  std::cout << "Key not found" << std::endl;
} else {
  // Some other error
  std::cerr << "Error: " << s.ToString() << std::endl;
}

Common Status Methods

ok()
bool
Returns true if the operation succeeded
IsNotFound()
bool
Returns true if the key was not found
IsCorruption()
bool
Returns true if data corruption was detected
IsIOError()
bool
Returns true if an I/O error occurred
ToString()
std::string
Returns a human-readable error message

Important Options

Database Options

Options options;

// Create database if missing
options.create_if_missing = true;

// Error if database already exists
options.error_if_exists = false;

// Optimize for your workload
options.IncreaseParallelism();          // Use all CPU cores
options.OptimizeLevelStyleCompaction(); // Optimize for level compaction

// Set write buffer size (default: 64MB)
options.write_buffer_size = 64 * 1024 * 1024;

// Maximum number of write buffers
options.max_write_buffer_number = 3;

Write Options

WriteOptions write_options;

// Synchronous writes (slower but safer)
write_options.sync = true;

// Disable write-ahead log (faster but less durable)
write_options.disableWAL = false;

Read Options

ReadOptions read_options;

// Use a snapshot for consistent reads
read_options.snapshot = db->GetSnapshot();

// Fill block cache
read_options.fill_cache = true;

Next Steps

Column Families

Learn how to partition your data logically

Transactions

Implement ACID transactions

Iterators

Scan ranges of keys efficiently

Backup & Restore

Protect your data with backups

Common Pitfalls

Memory Management: Always delete the DB object when done, or use std::unique_ptr<DB> for automatic cleanup. Close all iterators before closing the database.
Error Handling: Always check the Status returned by RocksDB operations. Ignoring errors can lead to data loss or corruption.
PinnableSlice Reuse: Always call Reset() on a PinnableSlice before reusing it. The slice is invalid after reset until the next Get call.

Running the Example

# Compile the example
g++ -std=c++20 -o simple_example simple_example.cc -lrocksdb

# Run it
./simple_example

# Check the created database
ls -la /tmp/rocksdb_simple_example/
Congratulations! You’ve created your first RocksDB application. Continue exploring the documentation to learn about advanced features.

Build docs developers (and LLMs) love