Oblien
Tutorial

How to Connect AI Agents to Private Databases Without Exposing Them

Securely wire AI agents to private databases without exposing them to the internet. No public endpoints, no VPNs - just private networking.

Oblien Team profile picture
Oblien Team
1 min read

How to Connect AI Agents to Private Databases Without Exposing Them

Your AI agent needs data. Maybe it queries a knowledge base to answer user questions. Maybe it stores conversation history. Maybe it manages user profiles or tracks tasks.

That means your agent needs database access.

The obvious approach - give the agent a database connection string pointing to a public endpoint - is also the most dangerous. You're exposing your database to the internet, protected only by a password. One leaked credential, one SQL injection, one misconfigured firewall rule, and your data is gone.

There's a better way: private networking. Your agent and your database run in separate environments, connected by a direct, encrypted link that's invisible to the rest of the internet.

Here's how to set it up.


Why you should never expose your database publicly

Let's start with why the "just make it public" approach is so bad:

Brute force attacks. The moment your database port is public, bots will find it. They scan every IP on common ports (3306, 5432, 27017) constantly. Even with a strong password, you're in a race against automated credential stuffing.

Leaked credentials. API keys and database passwords end up in git repos, env files, logs, and error messages. If the database is only reachable from a private network, a leaked password is useless to an attacker who can't reach the endpoint.

Zero-day vulnerabilities. Postgres, MySQL, MongoDB - they all have vulnerabilities. If your database isn't exposed to the internet, a zero-day in the database software is much harder to exploit.

AI-specific risks. Your AI agent builds queries based on natural language input. Prompt injection can trick the agent into running unexpected queries. If the database is only accessible from the agent's workspace (not the internet), the attack surface is limited to what the agent can do - not what anyone on the internet can do.


The architecture: Agent workspace + Database workspace

The cleanest setup is two separate environments connected by a private link:

                    Private Network (10.x.x.x)

┌──────────────────┐       │       ┌──────────────────┐
│  Agent Workspace │ ◄─────┼──────►│ Database Workspace│
│                  │  port 5432    │                   │
│  Your AI agent   │       │       │  PostgreSQL       │
│  framework       │       │       │  Your data        │
│                  │       │       │                   │
│  Internet: Yes   │       │       │  Internet: No     │
│  Public: Optional│       │       │  Public: No       │
└──────────────────┘       │       └───────────────────┘

               No other workspace can
               reach this database

Agent workspace - Runs your AI agent. Has internet access (to call the LLM API). May or may not have a public endpoint.

Database workspace - Runs PostgreSQL (or MySQL, Redis, etc.). Has NO internet access. Has NO public endpoint. The only thing that can reach it is the agent workspace, via a private link.

Even if someone compromises another workspace on the same account, they can't reach the database. The connection is explicitly limited to the agent workspace.


Setting it up step by step

Step 1: Create the database workspace

Create a workspace specifically for your database. Use a database image and disable internet access:

const dbWorkspace = await ws.create({
  image: 'postgres-16',
  cpus: 2,
  memory_mb: 4096,
  writable_size_mb: 20480,  // plenty of room for data
  allow_internet: false,     // completely air-gapped
  env: {
    POSTGRES_PASSWORD: 'your-secure-password',
    POSTGRES_DB: 'agent_data',
  },
});

This database has:

  • No internet access (can't be reached from the outside)
  • No public endpoint (no HTTPS preview URL)
  • No connections from other workspaces (zero-trust default)
  • Its own encrypted disk (AES-256, unique key)

It's completely invisible to everything.

Step 2: Create the agent workspace

const agentWorkspace = await ws.create({
  image: 'node-22',
  cpus: 2,
  memory_mb: 4096,
  writable_size_mb: 10240,
  env: {
    OPENAI_API_KEY: 'sk-...',
  },
});

Wire the agent workspace to the database workspace. This creates a directed network path:

await ws.network.update(dbWorkspace.id, {
  private_link_ids: [agentWorkspace.id],
  ingress_ports: [5432],
});

Now:

  • The agent workspace can connect to the database workspace on port 5432
  • No other workspace can connect to the database
  • The database can't initiate connections to the agent (it's one-way)
  • Traffic goes over the private 10.x.x.x network - never touches the internet

Step 4: Connect from the agent

From inside the agent workspace, connect to the database using its internal IP:

import pg from 'pg';

const pool = new pg.Pool({
  host: '10.x.x.x',  // database workspace's private IP
  port: 5432,
  database: 'agent_data',
  user: 'postgres',
  password: 'your-secure-password',
});

// Your agent can now query the database
const result = await pool.query('SELECT * FROM conversations WHERE user_id = $1', [userId]);

No public endpoints. No VPN. No SSH tunnels. Just a direct, private network connection between two workspaces.


Why this is more secure than traditional approaches

vs. Public database endpoint

A public endpoint means anyone who discovers the connection string can try to connect. With private networking, the database literally doesn't exist on the internet. You can't connect to it from outside the private network, period.

vs. VPC/VPN setup

Traditional VPC networking allows all resources within the VPC to communicate by default. You add security groups and network policies to restrict access, but misconfiguration is easy and common.

With Oblien's zero-trust model, the default is "nothing can connect." You explicitly add the one connection you need. There's nothing to misconfigure because there's nothing open by default.

vs. SSH tunnels

SSH tunnels are a common workaround: SSH into a bastion host, tunnel the database port locally. This works but adds operational complexity, introduces a single point of failure (the bastion), and requires SSH key management.

Private links are simpler: one API call, one directed connection. No bastion, no key management, no tunnel management.


Advanced patterns

Multiple agents, one database

If multiple agents need database access, add each agent workspace to the private link list:

await ws.network.update(dbWorkspace.id, {
  private_link_ids: [agentA.id, agentB.id],
  ingress_ports: [5432],
});

Agents A and B can both reach the database. But they can't reach each other (unless you set up a separate link). And no other workspace can reach the database.

Read replica pattern

For read-heavy workloads, create a second database workspace as a read replica:

  • Primary - receives writes from the orchestrator agent
  • Replica - read-only, connected to query agents

Agents that only need to read data connect to the replica. Even if a query agent is compromised, it can't modify data because it doesn't have access to the primary.

Per-user databases

In a multi-tenant application, each user gets their own database workspace. The user's agent workspace connects only to their database. User A's agent can't see user B's database - it's not on the network.

// Create user-specific database
const userDb = await ws.create({ image: 'postgres-16', allow_internet: false });

// Only this user's workspace can reach it
await ws.network.update(userDb.id, {
  private_link_ids: [userWorkspace.id],
  ingress_ports: [5432],
});

What about database backups?

Since the database workspace runs in an isolated VM with an encrypted disk, you need to think about backups:

Snapshots - Take a snapshot of the database workspace. This captures the full disk state. Restore from a snapshot for point-in-time recovery.

Archives - Create an archive of specific database directories. Good for scheduled backups.

pg_dump from the agent - Your agent workspace has a private link to the database. Run pg_dump from the agent workspace and store the backup on the agent's disk (or upload to an external backup service).

The key point: backups happen over the private network. The database never needs internet access, even for backups.


Summary

The safest way to give your AI agent database access:

  1. Run the database in its own workspace - isolated VM, encrypted disk, no internet
  2. Create a private link from the agent workspace to the database workspace
  3. Open only the database port (5432 for Postgres, 3306 for MySQL, etc.)
  4. Use internal IPs for the connection string - no public endpoints
  5. Keep the database air-gapped - no internet access, no public ports, invisible to everything except explicitly linked workspaces

Your agent gets full database access. Your database is invisible to the internet. A compromised agent in a different workspace can't reach it. And when the database workspace is eventually deleted, cryptographic erasure ensures the data is unrecoverable.

Learn about private networking →