Volcano/ Docs

Databases

Serverless PostgreSQL databases powered by Neon that auto-scale, pause when idle, and support row-level security.

Volcano provides serverless PostgreSQL databases powered by Neon. Databases auto-scale based on usage, pause when idle, and include built-in support for row-level security.

Features

FeatureDescription
ServerlessAuto-scales compute based on demand, pauses when idle
PostgreSQLFull PostgreSQL compatibility (versions 14, 15, 16)
Query BuilderQuery from browsers without writing SQL
Direct connectionConnect from Lambda with standard PostgreSQL clients
Row-level securityAutomatic data isolation per user
Auth helpersBuilt-in functions for user context (auth.uid(), auth.email())
Multiple databasesCreate multiple databases per project

Access methods

You can access your database two ways:

Query Builder (browser and mobile)

The Query Builder lets you query your database directly from frontend code using a chainable API:

import { VolcanoAuth } from '@volcano.dev/sdk';

const volcano = new VolcanoAuth({
  apiUrl: 'https://api.volcano.dev',
  anonKey: 'your-anon-key'
});
volcano.database('main');

// Sign in first
await volcano.auth.signIn({ email: 'user@example.com', password: 'password' });

// Query with the SDK
const { data, error } = await volcano
  .from('posts')
  .select('id, title, content')
  .eq('status', 'published')
  .order('created_at', { ascending: false })
  .limit(10);

The Query Builder:

  • Works directly from browsers
  • Enforces row-level security automatically
  • Doesn't require SQL knowledge
  • Supports filtering, ordering, and pagination

See Query Builder API for the complete reference.

Direct connection (Lambda functions)

Connect directly to PostgreSQL from your Lambda functions using any PostgreSQL client:

const { Client } = require('pg');

exports.handler = async (event) => {
  const client = new Client({
    connectionString: process.env.DATABASE_URL
  });

  await client.connect();

  const { rows } = await client.query(`
    SELECT id, title, content
    FROM posts
    WHERE status = 'published'
    ORDER BY created_at DESC
    LIMIT 10
  `);

  await client.end();

  return {
    statusCode: 200,
    body: JSON.stringify(rows)
  };
};

Direct connections:

  • Support full PostgreSQL features (JOINs, CTEs, transactions)
  • Work with ORMs (Sequelize, Prisma, TypeORM)
  • Can include user identity for RLS enforcement

See Direct connection for details.

Quick example

Create a database

curl -X POST "https://api.volcano.dev/projects/$PROJECT_ID/databases" \
  -H "Authorization: Bearer $PLATFORM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "main"}'

Response:

{
  "id": "db_abc123",
  "name": "main",
  "status": "creating",
  "region": "aws-us-east-1",
  "pg_version": 16
}

Use in a function

The DATABASE_URL environment variable is automatically set in all your functions:

const { Pool } = require('pg');

const pool = new Pool({
  connectionString: process.env.DATABASE_URL
});

exports.handler = async (event) => {
  const { rows } = await pool.query('SELECT NOW()');
  return {
    statusCode: 200,
    body: JSON.stringify({ time: rows[0].now })
  };
};

Auth helpers

When you create a database, Volcano automatically installs authentication helper functions:

FunctionReturnsDescription
auth.uid()UUIDCurrent user's ID
auth.email()TEXTCurrent user's email
auth.role()TEXTCurrent user's role (authenticated or anonymous)
auth.is_authenticated()BOOLEANWhether a user is authenticated

Use these in row-level security policies:

-- Users can only see their own posts
CREATE POLICY "users_own_posts" ON posts
  FOR ALL USING (user_id = auth.uid());

See Auth helpers for details.

Row-level security

Row-level security (RLS) lets you define policies that control which rows each user can access. Combined with auth helpers, you can write policies that automatically filter data:

-- Enable RLS on the table
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;

-- Users can read all published posts
CREATE POLICY "public_posts" ON posts
  FOR SELECT USING (status = 'published');

-- Users can only modify their own posts
CREATE POLICY "own_posts" ON posts
  FOR ALL USING (user_id = auth.uid());

When a user queries the posts table, PostgreSQL automatically applies these policies based on the user's identity.

See Row-level security for complete examples.

Authentication for database access

User access (RLS enforced)

When users sign in through your app, their queries are automatically scoped by RLS:

// User is signed in
await volcano.auth.signIn({ email: 'user@example.com', password: 'password' });

// Query returns only this user's data
const { data } = await volcano.from('posts').select('*');

Admin access (RLS bypassed)

Use a service key when you need to access all data regardless of RLS policies:

// Server-side only
const volcanoAdmin = new VolcanoAuth({
  apiUrl: process.env.VOLCANO_API_URL,
  anonKey: process.env.VOLCANO_ANON_KEY,
  accessToken: process.env.VOLCANO_SERVICE_KEY
});
volcanoAdmin.database('main');

// Returns all posts, not filtered by RLS
const { data } = await volcanoAdmin.from('posts').select('*');

Warning: Service keys bypass row-level security and can access all data. Never expose them in frontend code.

Regions and versions

Available regions

RegionLocation
aws-us-east-1US East (N. Virginia) — Default
aws-us-west-2US West (Oregon)
aws-eu-central-1Europe (Frankfurt)

Get the full list of available regions:

curl "https://api.volcano.dev/databases/regions" \
  -H "Authorization: Bearer $PLATFORM_TOKEN"

PostgreSQL versions

VersionStatus
16Latest, recommended
15Stable
14Legacy support

Specify the version when creating a database:

curl -X POST "https://api.volcano.dev/projects/$PROJECT_ID/databases" \
  -H "Authorization: Bearer $PLATFORM_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "main", "region": "aws-eu-central-1", "pg_version": 16}'

What's next

GuideDescription
Quick startSet up a database in 5 minutes
Creating databasesDatabase provisioning options
Query Builder APIComplete SDK query reference
REST APIHTTP endpoints for queries
Direct connectionConnect from Lambda functions
Row-level securitySecure data per user
Auth helpersSQL functions for user context
Connection stringsConnection details and pooling

On this page