or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

access-controllers.mdaddress-management.mddatabase-types.mdidentity-system.mdindex.mdoplog-system.mdorbitdb-factory.mdstorage-backends.md

storage-backends.mddocs/

0

# Storage Backends

1

2

OrbitDB provides a flexible storage system with multiple backend implementations for different use cases. Storage backends handle persistence of database entries, heads, and indices.

3

4

## Capabilities

5

6

### Storage Interface

7

8

All storage backends implement a common interface for consistency.

9

10

```javascript { .api }

11

interface Storage {

12

/** Stores data at the given key */

13

put(key: string, value: any): Promise<void>;

14

/** Retrieves data by key */

15

get(key: string): Promise<any>;

16

/** Deletes data at the given key */

17

del(key: string): Promise<void>;

18

/** Lists all keys (optional) */

19

keys?(): Promise<string[]>;

20

/** Clears all data (optional) */

21

clear?(): Promise<void>;

22

/** Closes the storage backend (optional) */

23

close?(): Promise<void>;

24

}

25

```

26

27

### IPFS Block Storage

28

29

Stores data as IPFS blocks, leveraging IPFS's content addressing and distributed storage.

30

31

```javascript { .api }

32

/**

33

* Creates an IPFS block storage instance

34

* @param params Configuration parameters

35

* @param params.ipfs IPFS instance to use

36

* @param params.pin Whether to pin blocks (default: false)

37

* @returns Promise resolving to IPFSBlockStorage instance

38

*/

39

function IPFSBlockStorage(params: {

40

ipfs: IPFS;

41

pin?: boolean;

42

}): Promise<IPFSBlockStorage>;

43

44

interface IPFSBlockStorage extends Storage {

45

/** Stores data as IPFS block */

46

put(hash: string, data: Uint8Array): Promise<void>;

47

/** Retrieves IPFS block data */

48

get(hash: string): Promise<Uint8Array>;

49

/** Unpins and removes IPFS block */

50

del(hash: string): Promise<void>;

51

}

52

```

53

54

**Usage Examples:**

55

56

```javascript

57

import { createHelia } from 'helia';

58

import { createOrbitDB, IPFSBlockStorage } from '@orbitdb/core';

59

60

const ipfs = await createHelia();

61

const orbitdb = await createOrbitDB({ ipfs });

62

63

// Create database with IPFS block storage

64

const db = await orbitdb.open('ipfs-stored-db', {

65

entryStorage: await IPFSBlockStorage({ ipfs, pin: true }),

66

headsStorage: await IPFSBlockStorage({ ipfs, pin: true })

67

});

68

69

// Data is stored as IPFS blocks

70

await db.add('This data is stored as IPFS blocks');

71

72

// Blocks are content-addressed and can be retrieved from any IPFS node

73

const entries = db.log.entries;

74

console.log('Entry stored at IPFS hash:', entries[0].hash);

75

```

76

77

### Level Storage

78

79

LevelDB-based storage for high-performance local persistence.

80

81

```javascript { .api }

82

/**

83

* Creates a Level storage instance

84

* @param params Configuration parameters

85

* @param params.path Directory path for LevelDB

86

* @param params.options LevelDB options

87

* @returns Promise resolving to LevelStorage instance

88

*/

89

function LevelStorage(params: {

90

path: string;

91

options?: any;

92

}): Promise<LevelStorage>;

93

94

interface LevelStorage extends Storage {

95

/** Stores key-value pair in LevelDB */

96

put(key: string, value: any): Promise<void>;

97

/** Retrieves value by key from LevelDB */

98

get(key: string): Promise<any>;

99

/** Deletes key from LevelDB */

100

del(key: string): Promise<void>;

101

/** Lists all keys in LevelDB */

102

keys(): Promise<string[]>;

103

/** Clears all data from LevelDB */

104

clear(): Promise<void>;

105

/** Closes LevelDB connection */

106

close(): Promise<void>;

107

}

108

```

109

110

**Usage Examples:**

111

112

```javascript

113

import { createOrbitDB, LevelStorage } from '@orbitdb/core';

114

115

const ipfs = await createHelia();

116

const orbitdb = await createOrbitDB({ ipfs });

117

118

// Create Level storage instances

119

const headsStorage = await LevelStorage({ path: './db-heads' });

120

const entryStorage = await LevelStorage({ path: './db-entries' });

121

const indexStorage = await LevelStorage({ path: './db-index' });

122

123

// Create database with Level storage

124

const db = await orbitdb.open('level-db', {

125

headsStorage,

126

entryStorage,

127

indexStorage

128

});

129

130

// Data persists to local LevelDB files

131

await db.add('Persistent data');

132

await db.close();

133

134

// Clean up storage

135

await headsStorage.close();

136

await entryStorage.close();

137

await indexStorage.close();

138

```

139

140

### LRU Storage

141

142

LRU (Least Recently Used) cache storage for memory-efficient operations with automatic eviction.

143

144

```javascript { .api }

145

/**

146

* Creates an LRU storage instance

147

* @param params Configuration parameters

148

* @param params.size Maximum number of items to cache (default: 1000)

149

* @returns Promise resolving to LRUStorage instance

150

*/

151

function LRUStorage(params?: {

152

size?: number;

153

}): Promise<LRUStorage>;

154

155

interface LRUStorage extends Storage {

156

/** Stores item in LRU cache */

157

put(key: string, value: any): Promise<void>;

158

/** Retrieves item from LRU cache */

159

get(key: string): Promise<any>;

160

/** Removes item from LRU cache */

161

del(key: string): Promise<void>;

162

/** Gets current cache size */

163

size(): number;

164

/** Clears the cache */

165

clear(): Promise<void>;

166

}

167

```

168

169

**Usage Examples:**

170

171

```javascript

172

import { createOrbitDB, LRUStorage } from '@orbitdb/core';

173

174

const ipfs = await createHelia();

175

const orbitdb = await createOrbitDB({ ipfs });

176

177

// Create LRU storage with custom size

178

const lruStorage = await LRUStorage({ size: 500 });

179

180

// Use as entry cache for frequently accessed data

181

const db = await orbitdb.open('cached-db', {

182

entryStorage: lruStorage

183

});

184

185

// Frequently accessed entries stay in memory

186

await db.add('Cached entry 1');

187

await db.add('Cached entry 2');

188

189

console.log('Cache size:', lruStorage.size());

190

191

// Older entries are evicted when cache is full

192

for (let i = 0; i < 600; i++) {

193

await db.add(`Entry ${i}`);

194

}

195

196

console.log('Cache size after overflow:', lruStorage.size()); // Still 500

197

```

198

199

### Memory Storage

200

201

In-memory storage for temporary data and testing scenarios.

202

203

```javascript { .api }

204

/**

205

* Creates a memory storage instance

206

* @returns Promise resolving to MemoryStorage instance

207

*/

208

function MemoryStorage(): Promise<MemoryStorage>;

209

210

interface MemoryStorage extends Storage {

211

/** Stores item in memory */

212

put(key: string, value: any): Promise<void>;

213

/** Retrieves item from memory */

214

get(key: string): Promise<any>;

215

/** Removes item from memory */

216

del(key: string): Promise<void>;

217

/** Lists all keys in memory */

218

keys(): Promise<string[]>;

219

/** Clears all data from memory */

220

clear(): Promise<void>;

221

}

222

```

223

224

**Usage Examples:**

225

226

```javascript

227

import { createOrbitDB, MemoryStorage } from '@orbitdb/core';

228

229

const ipfs = await createHelia();

230

const orbitdb = await createOrbitDB({ ipfs });

231

232

// Create in-memory database (no persistence)

233

const memoryStorage = await MemoryStorage();

234

const db = await orbitdb.open('temp-db', {

235

entryStorage: memoryStorage,

236

headsStorage: memoryStorage,

237

indexStorage: memoryStorage

238

});

239

240

// Data exists only in memory

241

await db.add('Temporary data');

242

await db.add('Will be lost on restart');

243

244

// Check memory contents

245

const keys = await memoryStorage.keys();

246

console.log('Stored keys:', keys);

247

248

// Clear all data

249

await memoryStorage.clear();

250

```

251

252

### Composed Storage

253

254

Combines multiple storage backends into a hierarchical storage system.

255

256

```javascript { .api }

257

/**

258

* Creates a composed storage instance

259

* @param storages Array of storage backends in order of preference

260

* @returns Promise resolving to ComposedStorage instance

261

*/

262

function ComposedStorage(storages: Storage[]): Promise<ComposedStorage>;

263

264

interface ComposedStorage extends Storage {

265

/** Stores item in all storage backends */

266

put(key: string, value: any): Promise<void>;

267

/** Retrieves item from first available storage backend */

268

get(key: string): Promise<any>;

269

/** Removes item from all storage backends */

270

del(key: string): Promise<void>;

271

/** Closes all storage backends */

272

close(): Promise<void>;

273

}

274

```

275

276

**Usage Examples:**

277

278

```javascript

279

import {

280

createOrbitDB,

281

ComposedStorage,

282

MemoryStorage,

283

LevelStorage,

284

IPFSBlockStorage

285

} from '@orbitdb/core';

286

287

const ipfs = await createHelia();

288

const orbitdb = await createOrbitDB({ ipfs });

289

290

// Create hierarchical storage: Memory -> Level -> IPFS

291

const composedStorage = await ComposedStorage([

292

await MemoryStorage(), // Fast L1 cache

293

await LevelStorage({ path: './cache' }), // L2 persistent cache

294

await IPFSBlockStorage({ ipfs }) // L3 distributed storage

295

]);

296

297

// Create database with composed storage

298

const db = await orbitdb.open('composed-db', {

299

entryStorage: composedStorage

300

});

301

302

// Data is stored in all layers but retrieved from fastest available

303

await db.add('Multi-layer stored data');

304

305

// Reads are served from memory when available

306

const allData = await db.all(); // Fast memory read

307

console.log('Data retrieved:', allData);

308

```

309

310

### Custom Storage Backends

311

312

Create custom storage backends for specific requirements.

313

314

```javascript { .api }

315

/**

316

* Template for custom storage implementation

317

*/

318

interface CustomStorage extends Storage {

319

put(key: string, value: any): Promise<void>;

320

get(key: string): Promise<any>;

321

del(key: string): Promise<void>;

322

keys?(): Promise<string[]>;

323

clear?(): Promise<void>;

324

close?(): Promise<void>;

325

}

326

```

327

328

**Usage Examples:**

329

330

```javascript

331

// Example: Redis-based storage backend

332

class RedisStorage {

333

constructor(redisClient) {

334

this.redis = redisClient;

335

}

336

337

async put(key, value) {

338

await this.redis.set(key, JSON.stringify(value));

339

}

340

341

async get(key) {

342

const value = await this.redis.get(key);

343

return value ? JSON.parse(value) : null;

344

}

345

346

async del(key) {

347

await this.redis.del(key);

348

}

349

350

async keys() {

351

return this.redis.keys('*');

352

}

353

354

async clear() {

355

const keys = await this.keys();

356

if (keys.length > 0) {

357

await this.redis.del(...keys);

358

}

359

}

360

361

async close() {

362

await this.redis.quit();

363

}

364

}

365

366

// Usage with OrbitDB

367

const redis = new Redis(); // Redis client

368

const redisStorage = new RedisStorage(redis);

369

370

const db = await orbitdb.open('redis-db', {

371

entryStorage: redisStorage

372

});

373

```

374

375

### S3-Compatible Storage Example

376

377

```javascript

378

// Example: S3-compatible storage backend

379

class S3Storage {

380

constructor(s3Client, bucketName) {

381

this.s3 = s3Client;

382

this.bucket = bucketName;

383

}

384

385

async put(key, value) {

386

await this.s3.putObject({

387

Bucket: this.bucket,

388

Key: key,

389

Body: JSON.stringify(value),

390

ContentType: 'application/json'

391

}).promise();

392

}

393

394

async get(key) {

395

try {

396

const result = await this.s3.getObject({

397

Bucket: this.bucket,

398

Key: key

399

}).promise();

400

return JSON.parse(result.Body.toString());

401

} catch (error) {

402

if (error.code === 'NoSuchKey') {

403

return null;

404

}

405

throw error;

406

}

407

}

408

409

async del(key) {

410

await this.s3.deleteObject({

411

Bucket: this.bucket,

412

Key: key

413

}).promise();

414

}

415

416

async keys() {

417

const result = await this.s3.listObjectsV2({

418

Bucket: this.bucket

419

}).promise();

420

return result.Contents.map(obj => obj.Key);

421

}

422

423

async clear() {

424

const keys = await this.keys();

425

if (keys.length > 0) {

426

await this.s3.deleteObjects({

427

Bucket: this.bucket,

428

Delete: {

429

Objects: keys.map(Key => ({ Key }))

430

}

431

}).promise();

432

}

433

}

434

}

435

436

// Usage

437

const s3Storage = new S3Storage(s3Client, 'my-orbitdb-bucket');

438

const db = await orbitdb.open('s3-db', {

439

entryStorage: s3Storage

440

});

441

```

442

443

### Storage Configuration Strategies

444

445

Different strategies for configuring storage backends based on use cases.

446

447

```javascript

448

import {

449

createOrbitDB,

450

MemoryStorage,

451

LevelStorage,

452

IPFSBlockStorage,

453

ComposedStorage

454

} from '@orbitdb/core';

455

456

const ipfs = await createHelia();

457

const orbitdb = await createOrbitDB({ ipfs });

458

459

// Strategy 1: All in memory (development/testing)

460

const devDb = await orbitdb.open('dev-db', {

461

headsStorage: await MemoryStorage(),

462

entryStorage: await MemoryStorage(),

463

indexStorage: await MemoryStorage()

464

});

465

466

// Strategy 2: Persistent local storage (production)

467

const prodDb = await orbitdb.open('prod-db', {

468

headsStorage: await LevelStorage({ path: './prod/heads' }),

469

entryStorage: await LevelStorage({ path: './prod/entries' }),

470

indexStorage: await LevelStorage({ path: './prod/index' })

471

});

472

473

// Strategy 3: Hybrid storage (performance + persistence)

474

const hybridDb = await orbitdb.open('hybrid-db', {

475

headsStorage: await ComposedStorage([

476

await MemoryStorage(),

477

await LevelStorage({ path: './heads' })

478

]),

479

entryStorage: await ComposedStorage([

480

await LRUStorage({ size: 1000 }),

481

await LevelStorage({ path: './entries' }),

482

await IPFSBlockStorage({ ipfs })

483

]),

484

indexStorage: await LevelStorage({ path: './index' })

485

});

486

487

// Strategy 4: Distributed storage (IPFS-first)

488

const distributedDb = await orbitdb.open('distributed-db', {

489

entryStorage: await IPFSBlockStorage({ ipfs, pin: true }),

490

headsStorage: await ComposedStorage([

491

await MemoryStorage(),

492

await IPFSBlockStorage({ ipfs, pin: true })

493

]),

494

indexStorage: await LevelStorage({ path: './index' })

495

});

496

```

497

498

### Storage Monitoring and Metrics

499

500

Monitor storage performance and usage.

501

502

```javascript

503

// Wrapper for storage monitoring

504

class MonitoredStorage {

505

constructor(storage, name) {

506

this.storage = storage;

507

this.name = name;

508

this.metrics = {

509

puts: 0,

510

gets: 0,

511

dels: 0,

512

errors: 0

513

};

514

}

515

516

async put(key, value) {

517

try {

518

const start = Date.now();

519

await this.storage.put(key, value);

520

this.metrics.puts++;

521

console.log(`${this.name} PUT ${key} took ${Date.now() - start}ms`);

522

} catch (error) {

523

this.metrics.errors++;

524

throw error;

525

}

526

}

527

528

async get(key) {

529

try {

530

const start = Date.now();

531

const result = await this.storage.get(key);

532

this.metrics.gets++;

533

console.log(`${this.name} GET ${key} took ${Date.now() - start}ms`);

534

return result;

535

} catch (error) {

536

this.metrics.errors++;

537

throw error;

538

}

539

}

540

541

async del(key) {

542

try {

543

const start = Date.now();

544

await this.storage.del(key);

545

this.metrics.dels++;

546

console.log(`${this.name} DEL ${key} took ${Date.now() - start}ms`);

547

} catch (error) {

548

this.metrics.errors++;

549

throw error;

550

}

551

}

552

553

getMetrics() {

554

return { ...this.metrics };

555

}

556

}

557

558

// Usage

559

const levelStorage = await LevelStorage({ path: './monitored' });

560

const monitoredStorage = new MonitoredStorage(levelStorage, 'Level');

561

562

const db = await orbitdb.open('monitored-db', {

563

entryStorage: monitoredStorage

564

});

565

566

// Operations are automatically monitored

567

await db.add('Monitored operation');

568

console.log('Storage metrics:', monitoredStorage.getMetrics());

569

```

570

571

### Error Handling

572

573

Handle storage-related errors appropriately.

574

575

```javascript

576

import { LevelStorage, MemoryStorage } from '@orbitdb/core';

577

578

// Graceful fallback to memory storage

579

async function createResilientStorage(path) {

580

try {

581

return await LevelStorage({ path });

582

} catch (error) {

583

console.warn(`Failed to create Level storage at ${path}:`, error.message);

584

console.log('Falling back to memory storage');

585

return await MemoryStorage();

586

}

587

}

588

589

// Usage with error handling

590

try {

591

const storage = await createResilientStorage('./database');

592

const db = await orbitdb.open('resilient-db', {

593

entryStorage: storage

594

});

595

596

await db.add('Data with resilient storage');

597

} catch (error) {

598

console.error('Storage operation failed:', error.message);

599

}

600

601

// Storage cleanup on shutdown

602

process.on('SIGINT', async () => {

603

try {

604

await storage.close();

605

console.log('Storage closed cleanly');

606

} catch (error) {

607

console.error('Error closing storage:', error.message);

608

}

609

process.exit(0);

610

});

611

```

612

613

Storage backends provide the foundation for OrbitDB's data persistence, enabling everything from ephemeral in-memory databases to highly distributed IPFS-backed storage systems.