SurrealDB is designed to be run in many different ways and environments. Due to the separation of the storage and compute layers, SurrealDB can be run in embedded mode from within JavaScript environments. In JavaScript, SurrealDB can be run as an in-memory database, or it can persist data using IndexedDB in browser environments or SurrealKV in server environments.
The in-memory database is perfect for embedded applications, development, testing, caching, or temporary data. It provides the fastest performance as all data is stored in RAM, but data is lost when the connection closes.
The embedded database functionality requires installing both the JavaScript SDK and the appropriate engine plugin:
npm install surrealdb @surrealdb/node # For Node.js server environments # or npm install surrealdb @surrealdb/wasm # For browser environments
NoteThe JavaScript SDK works seamlessly with SurrealDB versions v2.0.0 to v2.3.6, ensuring compatibility with the latest features.
The simplest way to use an in-memory database instance of SurrealDB is to connect with the mem:// endpoint after configuring the appropriate engine.
Node.js example:
import { Surreal } from 'surrealdb'; import { surrealdbNodeEngines } from '@surrealdb/node'; const db = new Surreal({ engines: surrealdbNodeEngines(), }); await db.connect("mem://"); await db.use({ namespace: "test", database: "test" }); // Create a person const person = await db.create("person", { name: "John Doe", age: 30, email: "john@example.com" }); console.log("Created person:", person); // Query all people const people = await db.select("person"); console.log("All people:", people); // Update the person const updated = await db.update("person", { name: "John Doe", age: 31, email: "john@example.com" }); console.log("Updated person:", updated); // Run a SurrealQL query const result = await db.query( "SELECT * FROM person WHERE age > $min_age", { min_age: 25 } ); console.log("Query result:", result); // Delete all people await db.delete("person"); console.log("Deleted all people"); // Close the connection await db.close();
Browser example:
import { Surreal } from 'surrealdb'; import { surrealdbWasmEngines } from '@surrealdb/wasm'; const db = new Surreal({ engines: surrealdbWasmEngines(), }); await db.connect("mem://"); await db.use({ namespace: "test", database: "test" }); // Create a person const person = await db.create("person", { name: "John Doe", age: 30, email: "john@example.com" }); console.log("Created person:", person);
The IndexedDB storage engine enables SurrealDB to persist data in browser environments using the browser’s IndexedDB API. Data persists across browser sessions and page reloads.
Install the JavaScript SDK and the WebAssembly engine:
npm install surrealdb @surrealdb/wasm
The IndexedDB database can be created using the indxdb:// endpoint with a database name.
import { Surreal } from 'surrealdb'; import { surrealdbWasmEngines } from '@surrealdb/wasm'; const db = new Surreal({ engines: surrealdbWasmEngines(), }); // Connect to IndexedDB database await db.connect("indxdb://mydb"); await db.use({ namespace: "test", database: "test" }); // Data persists across page reloads const company = await db.create("company", { name: "TechStart" }); console.log(company); // After page reload, data is still available const companies = await db.select("company"); console.log(companies);
NoteIf you are using a bundler like Vite, Webpack, or Parcel, you may need to configure it to properly handle the WebAssembly engine. For Vite, add the following to your
vite.config.js:
vite.config.jsoptimizeDeps: { exclude: ["@surrealdb/wasm"], esbuildOptions: { target: "esnext", }, }, esbuild: { supported: { "top-level-await": true }, }
The SurrealKV storage engine enables SurrealDB to persist data to disk in server environments. It provides good performance while maintaining persistence across connections and application restarts.
Install the JavaScript SDK and the Node.js engine:
npm install surrealdb @surrealdb/node
The SurrealKV database can be created using the surrealkv:// endpoint with a path to the database directory.
import { Surreal } from 'surrealdb'; import { surrealdbNodeEngines } from '@surrealdb/node'; const db = new Surreal({ engines: surrealdbNodeEngines(), }); // Connect to SurrealKV database await db.connect("surrealkv://./mydb"); await db.use({ namespace: "test", database: "test" }); // Data persists across connections const company = await db.create("company", { name: "TechStart" }); console.log(company); // Close and reconnect await db.close(); // Reconnect to the same database const db2 = new Surreal({ engines: surrealdbNodeEngines(), }); await db2.connect("surrealkv://./mydb"); await db2.use({ namespace: "test", database: "test" }); // Data persists! const companies = await db2.select("company"); console.log(companies); await db2.close();
You can also use SurrealKV with versioning support for temporal queries:
await db.connect("surrealkv+versioned://./mydb");
mem://)indxdb://) - Browser Onlysurrealkv://) - Server Onlymem://, indxdb://, or surrealkv://) when:ws://, wss://, http://, or https://):// Non-persistent, fastest performance await db.connect("mem://");
// Persistent storage in browser await db.connect("indxdb://database-name");
// Persistent storage using file path await db.connect("surrealkv://./path/to/database"); // With versioning support await db.connect("surrealkv+versioned://./path/to/database");
// WebSocket connection to remote server await db.connect("ws://localhost:8000"); // Secure WebSocket connection await db.connect("wss://cloud.surrealdb.com"); // HTTP connection to remote server await db.connect("http://localhost:8000"); // Secure HTTP connection await db.connect("https://cloud.surrealdb.com");
Embedded databases don’t require authentication, though you can still call signin() if needed:
// Embedded - auth optional (can be skipped) await db.connect("mem://"); await db.use({ namespace: "test", database: "test" }); // Ready to use! // Remote - requires authentication await db.connect("ws://localhost:8000"); await db.signin({ username: "root", password: "root" }); await db.use({ namespace: "test", database: "test" });
With embedded databases, the connection is established immediately when calling connect(). Always close connections when done:
// Good practice - close connection when done await db.connect("mem://"); // Do work here await db.close(); // Important for Node.js engine
NoteFor the Node.js engine, you must close the connection with
.close()to prevent console warnings. This is less critical for the WebAssembly engine in browsers.
Embedded databases are accessed by a single process or browser tab. For multi-process or distributed access, use a remote SurrealDB server.
@surrealdb/wasm with indxdb:// for persistence or mem:// for temporary data@surrealdb/node with surrealkv:// for persistence or mem:// for temporary dataAlways close connections when done, especially with the Node.js engine:
await db.connect("surrealkv://./mydb"); // Your code here await db.close(); // Important!
mem:// for speed and isolationsurrealkv:// (server) or indxdb:// (browser) for persistencesurrealkv:// (server) or indxdb:// (browser) with backupsIf you encounter import errors, ensure you have the correct packages installed:
npm install surrealdb @surrealdb/node # For Node.js # or npm install surrealdb @surrealdb/wasm # For browser
Both engine plugins require ES modules (import), not CommonJS (require). Ensure your project uses ES modules or configure your bundler accordingly.
For SurrealKV databases, ensure the directory exists and you have write permissions:
import { mkdir } from 'fs/promises'; const dbPath = "./mydata/database"; await mkdir(dbPath, { recursive: true }); await db.connect(`surrealkv://${dbPath}`);
If experiencing slow performance: