Oracle Database's Node.js driver (oracledb) requires Oracle Instant Client — a native C library that cannot compile in Bolt's WebContainer. The workaround is Oracle REST Data Services (ORDS), which exposes your Oracle DB via HTTP endpoints that work in WebContainers. For new Bolt projects, Supabase or Neon PostgreSQL are strongly recommended. This guide covers the ORDS approach for development and the native oracledb driver pattern for post-deployment use.
Oracle Database in Bolt.new: The WebContainer Constraint and the ORDS Solution
Oracle Database integration with Bolt.new runs into a fundamental constraint: the oracledb Node.js driver requires Oracle Instant Client, a set of native shared libraries written in C/C++ that must be installed at the OS level. Bolt's WebContainer runs Node.js inside a browser tab using WebAssembly — it cannot install OS-level packages, compile native modules, or load C shared libraries. When Bolt tries to install oracledb via npm, the package installs but fails to load because the underlying Oracle Instant Client is not present. You see errors like 'DPI-1047: 64-bit Oracle Client library cannot be loaded' or the module simply refuses to initialize.
The WebContainer constraint is compounded by a second problem specific to Oracle: TCP connections. Even if the native driver could load (which it cannot), WebContainers block raw TCP socket connections. Oracle Database communicates via the Oracle Net protocol over TCP (default port 1521), which the WebContainer's virtual networking layer does not support. This is the same TCP limitation that affects self-hosted MongoDB.
The solution for Bolt development is Oracle REST Data Services (ORDS). ORDS is an HTTP/HTTPS middleware that sits in front of Oracle Database and exposes tables, views, and stored procedures as RESTful endpoints. Calls go over HTTPS using standard fetch() — no native drivers, no TCP sockets. ORDS is available as a standalone installation for on-premises Oracle databases and comes pre-configured on Oracle Cloud Autonomous Database. Once your Oracle DBA enables ORDS on your database schema, you can query and mutate data in the Bolt preview just like any other REST API.
For teams evaluating whether to use Oracle with Bolt at all: if you are starting a new project without a pre-existing Oracle investment, Supabase (PostgreSQL) or Neon (PostgreSQL) are significantly easier to work with in Bolt. They use HTTP-based clients that work natively in the WebContainer, have generous free tiers, and provide modern developer experiences. Oracle makes sense when you have existing Oracle infrastructure, enterprise licensing, or Oracle-specific features (partitioning, Oracle Text, Oracle Spatial) that you need.
Integration method
Oracle Database's oracledb Node.js driver requires native C extensions (Oracle Instant Client) that cannot be compiled or loaded in Bolt's WebContainer environment. The recommended development approach is Oracle REST Data Services (ORDS), which exposes Oracle DB tables and procedures as HTTP REST endpoints accessible via fetch() in the WebContainer. After deploying to Netlify or Vercel, you can switch to the native oracledb driver with full TCP connectivity. Oracle Cloud's Autonomous Database ships with ORDS pre-enabled, making it the easiest Oracle option for Bolt development.
Prerequisites
- An Oracle Database instance with ORDS installed and configured on the schema you want to access (or Oracle Cloud Autonomous Database with ORDS pre-enabled)
- ORDS endpoint URL and credentials (basic auth username/password) for REST access to your Oracle schema
- A Bolt.new project using Next.js for API routes
- For post-deployment native driver setup: a Netlify or server environment where Oracle Instant Client can be installed
- Alternatively: Supabase or Neon account if evaluating Oracle alternatives
Step-by-step guide
Understand the Oracle WebContainer Limitation
Understand the Oracle WebContainer Limitation
The oracledb npm package has a hard requirement on Oracle Instant Client — a set of native shared libraries that must be present on the operating system running Node.js. When you add oracledb to a Bolt project, the npm install succeeds, but the module cannot load because there is no way to install Oracle Instant Client in the WebContainer's virtual filesystem. The error at runtime is: 'Error: DPI-1047: 64-bit Oracle Client library cannot be loaded. See https://oracle.github.io/odpi/doc/installation.html'. Even if Instant Client could be installed somehow, there is a second constraint: WebContainers block raw TCP connections, and Oracle Net (the protocol oracledb uses to talk to Oracle Database) requires TCP connectivity to port 1521 (or your configured Oracle listener port). This is the same TCP blocking that affects MongoDB's native driver. This means: code using oracledb, db.execute(), or oracle connection strings will never work in the Bolt WebContainer preview. The code is syntactically correct and will work after deployment to a real Node.js environment (Netlify, Vercel, EC2, etc.) where Instant Client can be installed. But you cannot test it during Bolt development. The practical path forward has two branches: 1. Use ORDS for development AND production (simpler, works everywhere, slightly higher latency per query due to HTTP overhead) 2. Use ORDS for development, switch to oracledb for production (best performance, more complex setup) For most Bolt projects, option 1 (ORDS everywhere) is the right choice unless you need stored procedures, complex Oracle-specific SQL, or have performance-critical query volumes. The ORDS approach also means zero config changes when moving between environments.
Create a .env file with Oracle connection variables as placeholders: ORACLE_ORDS_BASE_URL=https://your-oracle-host/ords/yourschema, ORACLE_ORDS_USER=your_ords_username, ORACLE_ORDS_PASSWORD=your_ords_password. Add a note explaining that native oracledb driver is not compatible with Bolt WebContainer (requires Oracle Instant Client C library) but ORDS HTTP API works perfectly. Create lib/oracle.ts with an oracleRequest helper that uses fetch() with Basic Auth headers to call ORDS endpoints.
Paste this in Bolt.new chat
1// ORACLE INTEGRATION OPTIONS:2//3// OPTION 1: ORDS (Oracle REST Data Services) — works EVERYWHERE including Bolt WebContainer4// - HTTP/HTTPS based, uses fetch()5// - Works in: Bolt preview, Netlify, Vercel, local Node.js6// - Setup: DBA enables ORDS on your Oracle schema7// - Oracle Cloud Autonomous DB: ORDS pre-enabled8//9// OPTION 2: Native oracledb driver — works ONLY after deployment10// - Requires Oracle Instant Client (C library at OS level)11// - Requires TCP connection to Oracle port 152112// - Works in: Netlify (with Instant Client layer), Vercel (with custom build), EC2/VPS13// - Does NOT work in: Bolt WebContainer preview14//15// RECOMMENDATION:16// - New projects: Consider Supabase (PostgreSQL) — HTTP-based, works natively in Bolt17// - Existing Oracle: Use ORDS for Bolt development18// - Enterprise production: oracledb after deployment if ORDS performance is a concern1920// Alternative (strongly recommended for new projects):21// Supabase: https://supabase.com — PostgreSQL, HTTP-based, works in Bolt WebContainerPro tip: Ask your Oracle DBA to enable ORDS on your development schema before starting. The DBA runs: EXEC ORDS.ENABLE_SCHEMA(p_enabled => TRUE, p_schema => 'YOUR_SCHEMA', p_auto_rest_auth => FALSE); This makes all tables in the schema accessible via HTTP REST automatically.
Expected result: You understand the WebContainer constraint and have decided on the ORDS approach for Bolt development. Your Oracle DBA has enabled ORDS on the target schema (or you are using Oracle Cloud Autonomous Database with ORDS pre-enabled).
Set Up Oracle REST Data Services (ORDS) HTTP Client
Set Up Oracle REST Data Services (ORDS) HTTP Client
Oracle REST Data Services provides automatic REST endpoints for Oracle Database tables when enabled on a schema. The endpoint pattern for a table named EMPLOYEES would be: GET https://your-oracle-host/ords/myschema/employees/ (list all rows), GET /ords/myschema/employees/{id} (get by primary key), POST /ords/myschema/employees/ (insert), PUT /ords/myschema/employees/{id} (update), DELETE /ords/myschema/employees/{id} (delete). For Oracle Cloud Autonomous Database, the ORDS base URL is provided in the Oracle Cloud Console: navigate to your Autonomous Database instance → Database Actions → SQL Workshop → REST. The URL format is: https://{instance-id}.adb.{region}.oraclecloudapps.com/ords/{schema}/. For on-premises ORDS installation: the URL depends on how your DBA configured ORDS — it may be on port 8080 (standalone), 443 (with a reverse proxy), or integrated with Oracle WebLogic. Get the base URL from your Oracle DBA. Authentication for ORDS can be configured in several ways: Basic Auth (username/password), OAuth2 tokens (ORDS has a built-in OAuth server), or no auth (for development schemas only). For Bolt integration, Basic Auth with an ORDS-specific user is the simplest path. Create an ORDS REST-enabled user in Oracle DB: CREATE USER ords_api IDENTIFIED BY password; GRANT CONNECT, RESOURCE TO ords_api; Then configure this user in ORDS. Use these credentials in your .env file — never expose them to the browser. For custom queries beyond simple table CRUD, ORDS supports SQL Workshop (execute arbitrary SQL via POST), custom RESTful modules (define custom endpoints backed by SQL queries or PL/SQL procedures), and parameterized queries via REST-enabled modules. For a Bolt integration, the auto-enabled table endpoints plus SQL Workshop cover 95% of use cases.
Build the complete Oracle ORDS HTTP client in lib/oracle.ts. Create an oracleRequest function that adds Basic Auth headers from ORACLE_ORDS_USER and ORACLE_ORDS_PASSWORD and handles both GET (query params) and POST/PUT/DELETE (JSON body) requests to ORACLE_ORDS_BASE_URL. Export: getRows(table, params), getRow(table, id), createRow(table, data), updateRow(table, id, data), deleteRow(table, id), and executeSQL(sqlQuery) using ORDS SQL Workshop endpoint. Handle ORDS error responses (returns JSON with 'type', 'title', 'detail' fields for errors).
Paste this in Bolt.new chat
1// lib/oracle.ts2const BASE = process.env.ORACLE_ORDS_BASE_URL!;3const USER = process.env.ORACLE_ORDS_USER!;4const PASS = process.env.ORACLE_ORDS_PASSWORD!;56const AUTH = Buffer.from(`${USER}:${PASS}`).toString('base64');78async function oracleRequest<T>(9 path: string,10 options: RequestInit = {}11): Promise<T> {12 const res = await fetch(`${BASE}${path}`, {13 ...options,14 headers: {15 Authorization: `Basic ${AUTH}`,16 'Content-Type': 'application/json',17 Accept: 'application/json',18 ...options.headers,19 },20 });2122 if (!res.ok) {23 let detail = `HTTP ${res.status}`;24 try {25 const err = await res.json() as { title?: string; detail?: string };26 detail = err.detail ?? err.title ?? detail;27 } catch { /* ignore parse error */ }28 throw new Error(`Oracle ORDS error: ${detail}`);29 }3031 return res.json();32}3334export const oracle = {35 getRows: <T>(table: string, params: Record<string, string | number> = {}) => {36 const qs = new URLSearchParams(params as Record<string, string>).toString();37 return oracleRequest<{ items: T[]; count: number; hasMore: boolean }>(38 `/${table}/${qs ? '?' + qs : ''}`39 );40 },41 getRow: <T>(table: string, id: string | number) =>42 oracleRequest<T>(`/${table}/${id}`),43 createRow: <T>(table: string, data: unknown) =>44 oracleRequest<T>(`/${table}/`, {45 method: 'POST',46 body: JSON.stringify(data),47 }),48 updateRow: <T>(table: string, id: string | number, data: unknown) =>49 oracleRequest<T>(`/${table}/${id}`, {50 method: 'PUT',51 body: JSON.stringify(data),52 }),53 deleteRow: (table: string, id: string | number) =>54 oracleRequest<void>(`/${table}/${id}`, { method: 'DELETE' }),55};Pro tip: ORDS auto-REST endpoints use lowercase table names as the URL path by default (regardless of Oracle's uppercase convention). Verify your ORDS URL structure by navigating to your ORDS base URL in a browser — if auth is disabled on GET, you will see the available collections listed.
Expected result: The ORDS HTTP client is configured. oracle.getRows('employees') returns rows from the Oracle table in the Bolt preview. All CRUD operations work via HTTPS without any native driver or TCP connection.
Build Oracle Data API Routes in Next.js
Build Oracle Data API Routes in Next.js
Create the Next.js API routes that expose Oracle data to the React frontend. The pattern is the same as any other API integration in Bolt: your frontend calls your own /api/ routes, and those routes call Oracle ORDS using the oracle helper from lib/oracle.ts. This proxy pattern keeps ORDS credentials server-side and lets you add business logic (validation, filtering, access control) before data reaches the client. For read-heavy dashboards or reports, the ORDS query approach works well: build parameterized API routes that construct the appropriate table fetch or SQL query based on validated frontend parameters. For complex Oracle-specific queries (JOINs across multiple tables, analytical functions, window queries), use ORDS SQL Workshop if your DBA has enabled it — POST arbitrary SQL to the ORDS SQL endpoint and get back result sets. SQL Workshop endpoint: POST to /ords/{schema}/_/sql with a JSON body containing the SQL statement. Response contains column metadata and row data. This is extremely powerful for building data-intensive dashboards since you can run any read-only Oracle query from the Bolt preview without any native driver. For write operations (INSERT, UPDATE, DELETE), ORDS table endpoints handle standard cases. For batch inserts or transactions involving multiple tables, use PL/SQL procedures exposed via ORDS custom RESTful modules — your DBA creates the REST endpoint, and your Bolt app calls it as a simple HTTP POST. TypeScript typing for Oracle data: ORDS returns rows in the items array. Define TypeScript interfaces matching your Oracle table columns. ORDS uses uppercase column names by default (Oracle stores column names in uppercase). You can configure ORDS to return lowercase or camelCase via ORDS configuration, or map them in your API route response.
Create Next.js API routes for an Oracle Database-backed employee directory. Build: GET /api/employees (list employees, accept department and search query params), GET /api/employees/[id] (single employee detail), POST /api/employees (create employee — validate required fields), PATCH /api/employees/[id] (update employee), DELETE /api/employees/[id] (delete with confirmation). Import oracle helpers from lib/oracle.ts. Map Oracle uppercase column names to camelCase in responses. Add TypeScript interface for Employee type. Return appropriate HTTP status codes and error messages.
Paste this in Bolt.new chat
1// app/api/employees/route.ts2import { NextResponse } from 'next/server';3import { oracle } from '@/lib/oracle';45interface OracleEmployee {6 EMPLOYEE_ID: number;7 FIRST_NAME: string;8 LAST_NAME: string;9 EMAIL: string;10 DEPARTMENT_ID: number;11 JOB_ID: string;12 HIRE_DATE: string;13 SALARY: number;14}1516function mapEmployee(e: OracleEmployee) {17 return {18 id: e.EMPLOYEE_ID,19 firstName: e.FIRST_NAME,20 lastName: e.LAST_NAME,21 email: e.EMAIL,22 departmentId: e.DEPARTMENT_ID,23 jobId: e.JOB_ID,24 hireDate: e.HIRE_DATE,25 salary: e.SALARY,26 };27}2829export async function GET(request: Request) {30 try {31 const { searchParams } = new URL(request.url);32 const params: Record<string, string> = {};33 const department = searchParams.get('department');34 if (department) params.q = JSON.stringify({ DEPARTMENT_ID: Number(department) });35 const result = await oracle.getRows<OracleEmployee>('employees', params);36 return NextResponse.json(result.items.map(mapEmployee));37 } catch (error: unknown) {38 const e = error as { message: string };39 return NextResponse.json({ error: e.message }, { status: 500 });40 }41}4243export async function POST(request: Request) {44 try {45 const body = await request.json();46 const { firstName, lastName, email, departmentId, jobId, salary } = body;47 if (!firstName || !lastName || !email) {48 return NextResponse.json(49 { error: 'firstName, lastName, and email are required' },50 { status: 400 }51 );52 }53 const created = await oracle.createRow<OracleEmployee>('employees', {54 FIRST_NAME: firstName,55 LAST_NAME: lastName,56 EMAIL: email,57 DEPARTMENT_ID: departmentId,58 JOB_ID: jobId,59 SALARY: salary,60 });61 return NextResponse.json(mapEmployee(created), { status: 201 });62 } catch (error: unknown) {63 const e = error as { message: string };64 return NextResponse.json({ error: e.message }, { status: 500 });65 }66}Pro tip: ORDS supports filtering via the q query parameter which accepts a JSON object for equality filters: ?q={"DEPARTMENT_ID":10}. For more complex filtering (LIKE, BETWEEN, IN), use ORDS SQL Workshop or create custom parameterized modules in ORDS with your DBA.
Expected result: GET /api/employees returns Oracle employees in camelCase format. POST /api/employees creates a new employee record. All operations work in the Bolt preview via ORDS without any native driver installation.
Set Up Native oracledb Driver for Post-Deployment
Set Up Native oracledb Driver for Post-Deployment
Once you deploy to Netlify or a server environment, the native oracledb driver becomes available since Oracle Instant Client can be installed at the OS level. For Netlify specifically, you need to add an Instant Client layer to your build process. For a VPS (AWS EC2, DigitalOcean, etc.), install Instant Client via the OS package manager before deploying. For Netlify deployments, the recommended approach is to use the oracle instant client via a Docker-based build or a custom Netlify build plugin that downloads and installs the Instant Client during the build phase. Alternatively, configure Netlify to use a Docker build image that includes Oracle Instant Client pre-installed. Consult Netlify's documentation on custom build environments for the current approach. For a VPS deployment: apt-get install libaio1 on Ubuntu/Debian, then download Oracle Instant Client Basic and BasicLite packages from oracle.com/database/technologies/instant-client, extract to /opt/oracle/instantclient, and set LD_LIBRARY_PATH. After this, oracledb loads and connects normally. The oracledb connection string format: (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=your-oracle-host)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orcl))). For Oracle Cloud Autonomous Database, download the Wallet files from the Oracle Cloud console and configure the oracledb connection to use the wallet for mTLS authentication. For connection pooling (essential for serverless environments): oracledb.createPool() creates a pool of connections that are reused across function invocations. The same caching pattern used for mongoose in Next.js applies here — store the pool in a global variable to prevent creating a new pool on each request.
Create an optional native oracledb integration that activates when ORACLE_CONNECTION_STRING is set. In lib/oracle-native.ts, implement getOraclePool() that creates or returns a cached oracledb connection pool using ORACLE_CONNECTION_STRING, ORACLE_USER, ORACLE_PASSWORD from env. Export a query(sql, binds) function that gets a connection from the pool, executes the SQL with bind variables, and releases the connection. Add error handling for ORA- prefixed Oracle errors. Create a compatibility shim so api routes can import from lib/oracle-compat.ts which uses ORDS when ORACLE_ORDS_BASE_URL is set and oracledb when ORACLE_CONNECTION_STRING is set.
Paste this in Bolt.new chat
1// lib/oracle-native.ts (used post-deployment only)2import oracledb from 'oracledb';34let pool: oracledb.Pool | null = null;56export async function getOraclePool(): Promise<oracledb.Pool> {7 if (pool) return pool;8 pool = await oracledb.createPool({9 user: process.env.ORACLE_USER!,10 password: process.env.ORACLE_PASSWORD!,11 connectString: process.env.ORACLE_CONNECTION_STRING!,12 poolMin: 2,13 poolMax: 10,14 poolIncrement: 1,15 });16 console.log('Oracle connection pool created');17 return pool;18}1920export async function query<T = Record<string, unknown>>(21 sql: string,22 binds: unknown[] | Record<string, unknown> = []23): Promise<T[]> {24 const p = await getOraclePool();25 const conn = await p.getConnection();26 try {27 const result = await conn.execute<T>(28 sql,29 binds,30 { outFormat: oracledb.OUT_FORMAT_OBJECT }31 );32 return result.rows ?? [];33 } finally {34 await conn.close();35 }36}Pro tip: Always use bind variables (the binds parameter) for user-supplied values in SQL statements — never interpolate values directly into SQL strings. Oracle uses positional :1, :2 or named :paramName bind syntax. This prevents SQL injection and also improves performance since Oracle caches execution plans for parameterized queries.
Expected result: The native oracledb code is prepared and ready for post-deployment use. After installing Oracle Instant Client on the target server and setting ORACLE_CONNECTION_STRING, oracle-native.ts connects to Oracle and runs queries. The ORDS approach continues to work in Bolt preview.
Deploy to Netlify and Test Oracle Connectivity
Deploy to Netlify and Test Oracle Connectivity
Deploy your Bolt project to Netlify to test the full integration. For ORDS-based integration, deployment is straightforward — your Next.js API routes make HTTPS calls to the ORDS endpoint, and Netlify's serverless functions have full outbound networking. No special Oracle libraries are required on the Netlify deployment. Deploy via Bolt Settings → Applications → Netlify → Publish. In Netlify Dashboard → Site Settings → Environment Variables, add ORACLE_ORDS_BASE_URL, ORACLE_ORDS_USER, and ORACLE_ORDS_PASSWORD. If using the native driver post-deployment, add ORACLE_CONNECTION_STRING, ORACLE_USER, and ORACLE_PASSWORD. Trigger a redeploy after adding variables. For ORDS connectivity: your Oracle server (or Oracle Cloud instance) must be accessible from Netlify's serverless function IPs. Netlify uses AWS Lambda, which has dynamic IPs — you cannot use static IP allowlisting. If your Oracle server has a firewall that restricts incoming connections, you must either open it to all IPs with authentication, or use Oracle Cloud's network access controls (security lists) that allow all IPs but require valid credentials. For Oracle Cloud Autonomous Database, Network Access is configurable per-instance. Monitor ORDS connectivity using the /api/health endpoint: test a simple ORDS call and return the status. If the ORDS call fails after deployment, check Netlify function logs for network errors. Common issues: ORDS server IP/hostname not accessible from Netlify, incorrect credentials, or ORDS schema not REST-enabled. Webhook-like real-time Oracle events (Oracle Advanced Queuing, Oracle Change Notification) require incoming TCP connections to your app, which means they only work with a deployed URL. Bolt WebContainer's lack of a public URL makes testing these impossible during development — simulate with polling or deploy first.
Prepare my Oracle integration for Netlify deployment. Create netlify.toml with build command 'npm run build', publish directory '.next', Node 20, and @netlify/plugin-nextjs. Create a GET /api/health route that tests ORDS connectivity by fetching the list of available ORDS collections from the base URL and returns { status: 'ok', database: 'oracle-ords-connected', tables: [...] } on success or { status: 'error', message: '...' } on failure. Add a README-style comment in lib/oracle.ts explaining when to use ORDS vs native oracledb.
Paste this in Bolt.new chat
1# netlify.toml2[build]3 command = "npm run build"4 publish = ".next"56[build.environment]7 NODE_VERSION = "20"89[[plugins]]10 package = "@netlify/plugin-nextjs"Pro tip: Oracle Cloud Autonomous Database's ORDS endpoint is already HTTPS and publicly accessible by default. It does not require firewall configuration changes — just credentials. This makes Oracle Autonomous Database the easiest Oracle option for Bolt + Netlify integrations with no networking setup.
Expected result: The app is deployed to Netlify with Oracle credentials set. GET /api/health confirms ORDS connectivity from Netlify's network. All product/employee/data CRUD operations work in production via the ORDS HTTP API.
Common use cases
Enterprise Data Dashboard via Oracle ORDS
Build a read-only reporting dashboard in Bolt that queries existing Oracle Database tables via ORDS REST endpoints. The dashboard fetches data from your Oracle schemas (sales figures, inventory levels, customer records) and displays them in charts and tables — all using standard fetch() calls that work in the Bolt WebContainer. No native drivers or TCP connections needed during development.
Build an enterprise data dashboard connected to Oracle Database via ORDS. Create a Next.js API route at app/api/oracle/[...path]/route.ts that proxies requests to my ORDS endpoint at ORACLE_ORDS_BASE_URL/ords/myschema. The proxy should forward query parameters and add Basic Auth using ORACLE_ORDS_USER and ORACLE_ORDS_PASSWORD from env. Build a dashboard UI with cards showing: total orders (from /ords/myschema/orders?limit=0), revenue this month (from /ords/myschema/revenue), and a data table with pagination fetching from /ords/myschema/customers.
Copy this prompt to try it in Bolt.new
Oracle Autonomous Database Integration
Oracle Cloud Autonomous Database comes with ORDS pre-enabled and accessible via a public URL. Use it as the backend for a Bolt app without any on-premises Oracle installation. Oracle Autonomous Database Free Tier provides 2 instances with 20GB storage each at no cost — a practical option for building and testing Oracle-backed Bolt applications.
Connect my Bolt app to Oracle Autonomous Database (Cloud) via ORDS. The ORDS endpoint is at https://myinstance.adb.us-phoenix-1.oraclecloudapps.com/ords/myschema/. Create a lib/oracle.ts with an oracleGet and oraclePost helper using fetch() with Basic Auth headers from ORACLE_ORDS_USER and ORACLE_ORDS_PASSWORD env vars. Create a CRUD API for a products table: GET /api/products (list with pagination), POST /api/products (create), PATCH /api/products/[id] (update), DELETE /api/products/[id]. Build a simple product management UI connected to these routes.
Copy this prompt to try it in Bolt.new
Post-Deployment Native Oracle Driver Integration
For applications that are deployed to a server (not just the Bolt WebContainer) and need the full power of Oracle Database — stored procedures, Oracle-specific SQL features, connection pooling — set up the native oracledb driver to run after deployment to Netlify or a VPS. This use case covers writing the code in Bolt with ORDS for preview, then switching to oracledb in production.
Build my Oracle integration with a dual-mode data layer: use ORDS fetch() when ORACLE_ORDS_BASE_URL is set (for Bolt preview), and fall back to the native oracledb driver when ORACLE_CONNECTION_STRING is set (for production). Create lib/oracle.ts with a query(sql, binds) function that automatically selects the correct backend. For oracledb mode: use connection pooling via oracledb.createPool(). For ORDS mode: convert the SQL query to a ORDS SQL workshop call via POST /ords/_/sql. Show example usage with a parameterized SELECT query.
Copy this prompt to try it in Bolt.new
Troubleshooting
Error: DPI-1047: 64-bit Oracle Client library cannot be loaded in Bolt preview
Cause: This is the expected WebContainer limitation. The oracledb driver requires Oracle Instant Client (native C library) which cannot be installed in Bolt's WebContainer environment. This error is not caused by misconfiguration — it is a structural incompatibility.
Solution: Switch to the ORDS approach for Bolt development: use HTTP-based ORDS endpoints via fetch() instead of the native oracledb driver. Ask your Oracle DBA to enable ORDS on your schema. The native oracledb driver will work correctly after deploying to Netlify or a server with Instant Client installed.
ORDS fetch returns 401 Unauthorized or 403 Forbidden
Cause: The ORACLE_ORDS_USER or ORACLE_ORDS_PASSWORD credentials are incorrect, the user does not have REST access to the schema, or ORDS authentication is configured to require OAuth tokens rather than Basic Auth.
Solution: Verify credentials are correct by testing the ORDS URL in a browser or curl command with the same Basic Auth. Ask your DBA to confirm the REST user has been granted ORDS access. If the ORDS configuration requires OAuth, implement the ORDS OAuth token flow instead of Basic Auth — POST to /ords/schema/oauth/token with client_id and client_secret.
ORDS returns rows with uppercase column names (EMPLOYEE_ID, FIRST_NAME, etc.)
Cause: Oracle stores all object names in uppercase by default, and ORDS reflects this in its JSON responses. This is expected behavior.
Solution: Map Oracle uppercase column names to camelCase in your Next.js API route before sending the response to the frontend. Alternatively, configure ORDS to use a different JSON response format via ORDS annotations.
1// Map Oracle uppercase to camelCase in your route:2const mapEmployee = (row: OracleRow) => ({3 id: row.EMPLOYEE_ID,4 firstName: row.FIRST_NAME,5 email: row.EMAIL,6});ORDS returns 404 Not Found for a table endpoint that should exist
Cause: The table has not been REST-enabled in ORDS. Auto-REST only applies to tables in schemas where ORDS is enabled. The table may exist in the Oracle DB but ORDS has not been configured to expose it.
Solution: Ask your Oracle DBA to enable the specific table for REST: EXEC ORDS.ENABLE_OBJECT(p_enabled => TRUE, p_schema => 'YOUR_SCHEMA', p_object => 'YOUR_TABLE', p_object_type => 'TABLE', p_auto_rest_auth => FALSE);
Best practices
- Use Oracle REST Data Services (ORDS) for all Bolt.new development — it works in the WebContainer and in production without any native library installation
- Never attempt to use the native oracledb driver in Bolt's WebContainer — the Oracle Instant Client C library cannot load and TCP to port 1521 is blocked
- Store ORDS credentials (username/password) as server-only environment variables without NEXT_PUBLIC_ prefix
- Use bind variables in all SQL statements to prevent SQL injection and improve query plan caching: use ORDS parameterized modules or oracledb binds parameter
- Map Oracle uppercase column names (FIRST_NAME) to camelCase (firstName) in your API routes before sending to the frontend
- For new Bolt projects without existing Oracle infrastructure, strongly consider Supabase or Neon PostgreSQL — they work natively in WebContainers via HTTP clients without any workarounds
- If using Oracle Autonomous Database, enable network access for all IPs (with authentication) since Netlify and Vercel use dynamic IPs
- Test ORDS connectivity from a deployed environment before finalizing the integration — ORDS network access rules may differ between your development machine and Netlify's Lambda network
Alternatives
PostgreSQL via Supabase or Neon uses HTTP-based clients that work natively in Bolt's WebContainer preview without any workarounds, making it strongly preferred over Oracle for new Bolt projects.
SQL Server has similar enterprise database capabilities but can connect from Bolt via Azure SQL's REST endpoints or compatible HTTP APIs — still constrained by TCP limitations but with different HTTP options.
MySQL via PlanetScale's serverless driver uses HTTP connections that work in Bolt's WebContainer, and MySQL syntax is compatible with much Oracle SQL — making it a viable migration target for many applications.
MongoDB Atlas Data API communicates over HTTP and works in Bolt's WebContainer, providing a document-oriented alternative to Oracle's relational model with no TCP or native driver requirements.
Frequently asked questions
Why does the oracledb npm package fail to load in Bolt but not on my regular Node.js machine?
Your regular machine has Oracle Instant Client installed at the OS level (in /lib, /usr/lib, or a path set in LD_LIBRARY_PATH). Bolt's WebContainer simulates Node.js inside a browser tab using WebAssembly — it cannot install OS packages or load C shared libraries. The oracledb module tries to load Oracle Instant Client at runtime, fails to find it, and throws DPI-1047. This will never work in the WebContainer regardless of oracledb version.
Does Oracle ORDS have a cost?
ORDS (Oracle REST Data Services) is free to download and use — it is included with Oracle Database licenses. For Oracle Cloud (OCI), ORDS is pre-configured on Autonomous Database at no extra charge. The cost is the Oracle Database infrastructure itself, not ORDS. Oracle Cloud Free Tier includes 2 Autonomous Database instances at no cost, which is sufficient for Bolt development and testing.
Can I run stored procedures through ORDS from Bolt?
Yes. Your Oracle DBA can create custom ORDS RESTful modules that expose PL/SQL procedures as HTTP endpoints. A stored procedure PROCESS_ORDER(p_order_id) can be exposed as POST /ords/myschema/process-order with the parameters in the JSON request body. This allows Bolt to trigger complex Oracle business logic via HTTP without the native driver. Ask your DBA to create the RESTful module in Oracle SQL Developer or ORDS configuration.
Is ORDS suitable for production use or just development?
ORDS is production-ready and used by many Oracle Cloud customers as their primary REST API layer. For high-volume APIs, the HTTP overhead per query is slightly higher than a direct driver connection, but ORDS includes connection pooling and connection management internally. Oracle certifies ORDS for production use. The choice between ORDS and native oracledb in production depends on your performance requirements and whether the HTTP overhead (typically 5-20ms per request) is acceptable for your workload.
What if my Oracle Database is on a private network that Bolt's WebContainer cannot reach?
If your Oracle ORDS instance is on a private network (VPN, corporate intranet, no public IP), you cannot reach it from Bolt's WebContainer or from Netlify's serverless functions without additional networking. Options: (1) temporarily expose ORDS on a public IP with authentication for development, (2) use Oracle Cloud's VCN service networking if both are on OCI, or (3) develop against a local ORDS instance and use ngrok to tunnel it to a public URL during Bolt development. The cleanest long-term solution is Oracle Cloud Autonomous Database, which is publicly accessible with credential-based authentication.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation