Overview
Relational database storage using Bun's native SQL APIs
Store structured data with queries, joins, and transactions using Bun's native SQL APIs.
When to Use Database Storage
| Storage Type | Best For |
|---|---|
| Database | Structured data, complex queries, transactions, relational data |
| Key-Value | Fast lookups, caching, configuration |
| Vector | Semantic search, embeddings, RAG |
| Object (S3) | Files, images, documents, media |
| Durable Streams | Large exports, audit logs |
Credentials Auto-Injected
When you create a database with agentuity cloud db create, the DATABASE_URL is automatically added to your .env file. During deployment, credentials are injected automatically.
Creating a Database
# Create with default settings
agentuity cloud db create
# Create with name and description
agentuity cloud db create --name "users-db" --description "Primary user data store"Quick Start
import { sql } from "bun";
// Query with automatic SQL injection protection
const users = await sql`SELECT * FROM users WHERE active = ${true}`;
// Insert data
await sql`INSERT INTO users (name, email) VALUES (${"Alice"}, ${"alice@example.com"})`;
// Update data
await sql`UPDATE users SET active = ${false} WHERE id = ${userId}`;
// Delete data
await sql`DELETE FROM users WHERE id = ${userId}`;SQL Injection Prevention
Always use template literal parameters (${value}) for dynamic values. Never concatenate strings into queries.
Using in Agents
import { createAgent } from '@agentuity/runtime';
import { sql } from "bun";
const agent = createAgent('UserQuery', {
handler: async (ctx, input) => {
const users = await sql`
SELECT * FROM users
WHERE active = ${true}
AND created_at > ${input.since}
ORDER BY created_at DESC
LIMIT 10
`;
ctx.logger.info("Query results", { count: users.length });
return { users };
},
});Using in Routes
import { createRouter } from '@agentuity/runtime';
import { sql } from "bun";
const router = createRouter();
router.get('/users', async (c) => {
const limit = parseInt(c.req.query('limit') || '10');
const users = await sql`
SELECT id, name, email FROM users
ORDER BY created_at DESC
LIMIT ${limit}
`;
return c.json({ users });
});
router.post('/users', async (c) => {
const body = await c.req.json();
const result = await sql`
INSERT INTO users (name, email)
VALUES (${body.name}, ${body.email})
RETURNING id, name, email
`;
return c.json({ user: result[0] }, 201);
});
export default router;Transactions
Use transactions for operations that must succeed or fail together:
import { sql } from "bun";
await sql.begin(async (tx) => {
await tx`UPDATE accounts SET balance = balance - ${amount} WHERE id = ${fromAccount}`;
await tx`UPDATE accounts SET balance = balance + ${amount} WHERE id = ${toAccount}`;
await tx`INSERT INTO transfers (from_id, to_id, amount) VALUES (${fromAccount}, ${toAccount}, ${amount})`;
});Supported Databases
Bun's SQL API supports PostgreSQL, MySQL, and SQLite:
import { SQL } from "bun";
// PostgreSQL (default, uses DATABASE_URL)
const users = await sql`SELECT * FROM users`;
// Custom PostgreSQL connection
const postgres = new SQL("postgres://user:pass@localhost:5432/mydb");
// MySQL
const mysql = new SQL("mysql://user:pass@localhost:3306/mydb");
// SQLite
const sqlite = new SQL("sqlite://data/app.db");For complete Bun SQL documentation, see the Bun SQL docs.
Next Steps
- Resilient Postgres Client: Auto-reconnecting PostgreSQL client for serverless
- Drizzle ORM: Type-safe database access with Drizzle
- Key-Value Storage: Fast caching and session data
- Vector Storage: Semantic search and embeddings
Need Help?
Join our Community for assistance or just to hang with other humans building agents.
Send us an email at hi@agentuity.com if you'd like to get in touch.
Please Follow us on
If you haven't already, please Signup for your free account now and start building your first agent!