Documentation Index Fetch the complete documentation index at: https://docs.buntime.sh/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Persistence in buntime.sh means files, data, and state survive across multiple code executions within a session. Understanding how persistence works is crucial for building reliable applications and multi-step workflows.
What Persists
✅ Files in /workspace
All files created in the /workspace directory persist:
// First execution
await client . execute ({
sessionId: session . id ,
code: `
await Bun.write('data.json', JSON.stringify({ count: 0 }));
console.log('File created');
`
});
// Second execution - file still exists
await client . execute ({
sessionId: session . id ,
code: `
const data = await Bun.file('data.json').json();
data.count++;
await Bun.write('data.json', JSON.stringify(data));
console.log('Count:', data.count); // 1
`
});
✅ Installed Packages
Packages installed via bun add or auto-installed on import persist:
// First execution
await client . execute ({
sessionId: session . id ,
command: 'bun add lodash'
});
// Second execution - lodash is available
await client . execute ({
sessionId: session . id ,
code: `
import _ from 'lodash';
console.log(_.uniq([1, 2, 2, 3])); // [1, 2, 3]
`
});
✅ Database Files
SQLite and other file-based databases persist:
// First execution
await client . execute ({
sessionId: session . id ,
code: `
import { Database } from "bun:sqlite";
const db = new Database("mydb.sqlite");
db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)");
db.run("INSERT INTO users (name) VALUES ('Alice')");
db.close();
`
});
// Second execution - database still exists
await client . execute ({
sessionId: session . id ,
code: `
import { Database } from "bun:sqlite";
const db = new Database("mydb.sqlite");
const user = db.query("SELECT * FROM users").get();
console.log(user); // { id: 1, name: 'Alice' }
`
});
✅ Background Processes (While Active)
Processes started in previous executions keep running:
// First execution - start server
await client . execute ({
sessionId: session . id ,
code: `
Bun.serve({
port: 8080,
fetch() {
return new Response('Hello!');
}
});
console.log('Server started');
`
});
// Server keeps running in background
// Can be accessed at https://{sessionId}.buntime.sh
What Doesn’t Persist
❌ In-Memory Variables
Variables only exist during a single execution:
// First execution
await client . execute ({
sessionId: session . id ,
code: `let myVar = 'hello';`
});
// Second execution - myVar doesn't exist
await client . execute ({
sessionId: session . id ,
code: `console.log(myVar);` // ReferenceError: myVar is not defined
});
Workaround : Write to files:
// First execution
await client . execute ({
sessionId: session . id ,
code: `await Bun.write('state.json', JSON.stringify({ myVar: 'hello' }));`
});
// Second execution
await client . execute ({
sessionId: session . id ,
code: `
const state = await Bun.file('state.json').json();
console.log(state.myVar); // 'hello'
`
});
❌ Files Outside /workspace
Files created outside /workspace may not persist:
// ❌ Don't do this
await client . execute ({
sessionId: session . id ,
code: `await Bun.write('/tmp/data.txt', 'hello');`
});
Always use /workspace :
// ✅ Do this
await client . execute ({
sessionId: session . id ,
code: `await Bun.write('/workspace/data.txt', 'hello');`
// or simply: await Bun.write('data.txt', 'hello');
});
❌ Environment Variables
Environment variables don’t persist between executions:
// First execution
await client . execute ({
sessionId: session . id ,
code: `process.env.MY_VAR = 'test';`
});
// Second execution - MY_VAR doesn't exist
await client . execute ({
sessionId: session . id ,
code: `console.log(process.env.MY_VAR);` // undefined
});
Workaround : Pass env vars in each request or write to a file.
❌ Processes After Deep Sleep
Processes are terminated after 30 minutes of inactivity:
// Start a process
await client . execute ({
sessionId: session . id ,
code: `
Bun.serve({ port: 8080, fetch: () => new Response('OK') });
`
});
// After 30 minutes of no requests:
// - Session enters deep sleep
// - Server process is terminated
// - Files are saved to R2 storage
// On next request:
// - Session wakes up
// - Files are restored
// - Server process is NOT running
Persistence Across Session States
Active State
Everything persists in memory:
Files immediately accessible
Processes running
No I/O delays
Full speed
Idle State (5 min)
Container sleeps but everything remains:
Files still in memory
Processes suspended
Wake time: instant
State preserved
Deep Sleep (30 min)
Filesystem saved to storage:
Files saved to R2
Processes terminated
Wake time: ~3 seconds
File state preserved
After Wake
Files restored but processes restarted:
All files restored from R2
Need to restart servers
Database files intact
Package installations preserved
Storage Limits
Each session has disk space limits:
Plan Disk Space Free 1 GB Paid 5 GB Enterprise Custom
Monitor disk usage:
await client . execute ({
sessionId: session . id ,
code: `
import { spawnSync } from 'bun';
const result = spawnSync(['du', '-sh', '/workspace']);
console.log(result.stdout.toString());
`
});
Database Persistence Patterns
SQLite
Best for structured data:
await client . execute ({
sessionId: session . id ,
code: `
import { Database } from "bun:sqlite";
const db = new Database("app.db");
db.run( \`
CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
completed INTEGER DEFAULT 0
)
\` );
db.run("INSERT INTO todos (title) VALUES (?)", "Buy milk");
console.log("Todo saved");
`
});
JSON Files
Best for simple state:
await client . execute ({
sessionId: session . id ,
code: `
const state = {
counter: 0,
lastRun: new Date().toISOString(),
items: []
};
await Bun.write('state.json', JSON.stringify(state, null, 2));
`
});
Redis (In-Memory)
Best for caching and temporary data:
await client . execute ({
sessionId: session . id ,
code: `
// Note: Redis data is in-memory and lost on deep sleep
// Only use for temporary caching
import { createClient } from 'redis';
const redis = createClient();
await redis.connect();
await redis.set('key', 'value');
`
});
File Organization Best Practices
Organize by Purpose
/workspace/
├── data/ # Application data
│ ├── cache/
│ └── uploads/
├── src/ # Source code
│ ├── utils.ts
│ └── main.ts
├── db/ # Databases
│ └── app.db
└── config/ # Configuration
└── settings.json
Use Subdirectories
await client . execute ({
sessionId: session . id ,
code: `
import { mkdirSync } from 'fs';
// Create directory structure
mkdirSync('data/uploads', { recursive: true });
mkdirSync('src', { recursive: true });
mkdirSync('db', { recursive: true });
console.log('Directories created');
`
});
State Management Patterns
Counter Example
// Initialize
await client . execute ({
sessionId: session . id ,
code: `
const counter = { count: 0 };
await Bun.write('counter.json', JSON.stringify(counter));
`
});
// Increment
await client . execute ({
sessionId: session . id ,
code: `
const counter = await Bun.file('counter.json').json();
counter.count++;
await Bun.write('counter.json', JSON.stringify(counter));
console.log('Count:', counter.count);
`
});
Session Store Example
await client . execute ({
sessionId: session . id ,
code: `
class SessionStore {
constructor(filename = 'session.json') {
this.filename = filename;
}
async get(key) {
try {
const data = await Bun.file(this.filename).json();
return data[key];
} catch {
return null;
}
}
async set(key, value) {
let data = {};
try {
data = await Bun.file(this.filename).json();
} catch {}
data[key] = value;
await Bun.write(this.filename, JSON.stringify(data));
}
async delete(key) {
try {
const data = await Bun.file(this.filename).json();
delete data[key];
await Bun.write(this.filename, JSON.stringify(data));
} catch {}
}
}
const store = new SessionStore();
await store.set('user', { name: 'Alice', age: 30 });
console.log('Saved');
`
});
Backup and Recovery
Manual Backup
Download files before session expires:
// Read all files
const files = await client . files . list ({ sessionId: session . id });
for ( const file of files ) {
const content = await client . files . read ({
sessionId: session . id ,
path: file . path
});
// Save locally
await Bun . write ( `backup/ ${ file . path } ` , content );
}
Automatic Snapshots
buntime.sh automatically snapshots your workspace:
On idle (5 min): In-memory snapshot
On deep sleep (30 min): R2 snapshot
On wake: Restore from snapshot
Common Patterns
Always use file-based databases in /workspace: import { Database } from "bun:sqlite" ;
const db = new Database ( "/workspace/data.db" );
Save uploaded files to disk: const file = await req . formData (). get ( 'file' );
await Bun . write (\ `uploads/ \$ {file.name} \` , file);
Use JSON files for simple caches: const cache = await Bun . file ( 'cache.json' ). json (). catch (() => ({}));
cache [ key ] = value ;
await Bun . write ( 'cache.json' , JSON . stringify ( cache ));
Track when data was last modified: const data = {
content: 'hello' ,
updatedAt: new Date (). toISOString ()
};
await Bun . write ( 'data.json' , JSON . stringify ( data ));
Best Practices
Use /workspace Always write to /workspace to ensure persistence
Close connections Close database connections when done to free resources
Handle missing files Use try-catch when reading files that might not exist
Clean up Delete temporary files to stay within disk limits
Sessions Understanding session lifecycle
Resource Limits Disk space and memory limits
Files API Managing files via API
Databases Guide Working with databases