← All notes
2026-03-18·11 min read

Oracle ORDS 25.x Standalone High Availability Setup

oracleordsapexalta-disponibilidadlinuxArchitectureOraclehigh-availability

Installation Guide: Oracle REST Data Services (ORDS) 25.x in Standalone Mode

High Availability Deployment — 2 Nodes + Load Balancer

Version: 1.0
Date: March 2026
Applies to: ORDS 25.x · Oracle APEX 24.x · Oracle Linux 8/9 · Java 17


Table of Contents

  1. Introduction and Architecture
  2. Prerequisites
  3. Environment Reference Data
  4. Installation on Node 1
  5. Installation on Node 2
  6. Configuration as a systemd Service
  7. Load Balancer Configuration
  8. Environment Validation
  9. Parameter Reference

1. Introduction and Architecture

Oracle REST Data Services (ORDS) is the web gateway that enables access to Oracle APEX and exposes REST APIs over an Oracle database. In standalone mode, ORDS uses an embedded web server (Jetty) without requiring an application container such as WebLogic or Tomcat.

Why Standalone Mode?

  • It is the officially Oracle-recommended mode for new deployments
  • Eliminates the complexity of managing an additional application server
  • Supports Java 17+ without compatibility restrictions
  • Lower maintenance overhead and attack surface

Environment Architecture

ORDS Architecture

Note: Both nodes share the same ORDS configuration and point to the same database service. The Load Balancer distributes traffic between them using Round Robin.


2. Prerequisites

Before starting the installation, verify the following requirements are met on both nodes:

Operating System

  • Oracle Linux 8 or 9 (or equivalent RHEL)
  • oracle user with sudo access or root access available
  • SSH connectivity between nodes

Java

  • Oracle JDK 17 or higher installed
  • ORDS 25.x requires Java 17 as a minimum — earlier versions are not compatible

Database

  • Oracle Database 19c or higher
  • APEX 24.x installed and in VALID state in the target PDB
  • SYS AS SYSDBA credentials available
  • Connectivity from the nodes to the database SCAN listener

Disk Space

  • Minimum 2 GB free in the ORDS installation directory
  • Minimum 500 MB additional for APEX static images
  • Additional space for logs

Ports

  • Port 8080 available on both nodes (or the defined port)
  • Port 8080 enabled in the firewall toward the Load Balancer

3. Environment Reference Data

⚠️ Replace these values with your actual environment data before executing the commands.

Parameter Example Value Description
Node 1 hostname app-node1.mycompany.com Middleware server node 1
Node 2 hostname app-node2.mycompany.com Middleware server node 2
Load Balancer VIP ords.mycompany.com Balanced URL
ORDS port 8080 HTTP listening port
SCAN listener db-scan.mycompany.com Database SCAN hostname
DB port 1521 Listener port
PDB Service Name APPDB Target PDB service name
ORDS home /u02/app/ords ORDS installation directory
ORDS config /u02/app/ords/config Configuration directory
APEX images /u02/app/ords/apex_images Static images directory
ORDS logs /u02/app/ords/log Logs directory
Java home /u01/java/jdk-17 Java 17 directory
OS user oracle Operating system user

4. Installation on Node 1

All commands in this section are executed on app-node1 as the oracle user, unless otherwise indicated.

4.1 Verify Prerequisites

# Verify Java version
export JAVA_HOME=/u01/java/jdk-17
export PATH=$JAVA_HOME/bin:$PATH
java -version

Expected output:

java version "17.x.x" ...
Java HotSpot(TM) 64-Bit Server VM ...
# Verify available disk space
df -h /u02

# Verify connectivity to the database
tnsping db-scan.mycompany.com

4.2 Prepare Directory Structure

Create the necessary directories before proceeding.

mkdir -p /u02/app/ords
mkdir -p /u02/app/ords/config
mkdir -p /u02/app/ords/log
mkdir -p /u02/app/ords/apex_images
mkdir -p /u02/app/ords/deploy
mkdir -p /u02/app/ords/bin

# Verify created structure
ls -la /u02/app/ords/

4.3 Download and Install ORDS

Download the ords-25.x.x.zip file from Oracle Software Delivery Cloud or oracle.com/rest.

# Extract ORDS into the installation directory
cd /u02/app/ords
unzip /tmp/ords-25.x.x.zip

# Verify the binary exists
ls -la /u02/app/ords/bin/ords

# Add ORDS to PATH and verify version
export JAVA_HOME=/u01/java/jdk-17
export ORDS_HOME=/u02/app/ords
export PATH=$JAVA_HOME/bin:$ORDS_HOME/bin:$PATH

ords --version

Expected output:

ORDS: Release 25.x Production on [date]
Copyright (c) 2010, 2026, Oracle.
Oracle REST Data Services 25.x.x.rXXXXXXX

Note: The WARNING about the config folder location is informational and does not block operation.

4.4 Deploy APEX Static Images

ORDS in standalone mode requires APEX static images to be available locally. Extract them from the APEX installation ZIP.

# Extract images from APEX ZIP (adjust path to the ZIP file)
unzip /tmp/apex_24.x.zip "apex/images/*" -d /tmp/apex_extract/

# Copy images to the definitive directory
cp -r /tmp/apex_extract/apex/images/* /u02/app/ords/apex_images/

# Verify content
ls /u02/app/ords/apex_images/ | head -10
du -sh /u02/app/ords/apex_images/

4.5 Install ORDS into the Database

This step creates the ORDS_METADATA and ORDS_PUBLIC_USER schemas inside the target PDB. This is the longest step — it can take between 20 and 30 minutes depending on hardware.

export JAVA_HOME=/u01/java/jdk-17
export ORDS_HOME=/u02/app/ords
export PATH=$JAVA_HOME/bin:$ORDS_HOME/bin:$PATH

ords --config /u02/app/ords/config install \
  --admin-user SYS \
  --db-hostname db-scan.mycompany.com \
  --db-port 1521 \
  --db-servicename APPDB \
  --log-folder /u02/app/ords/log \
  --feature-sdw true

The installer will interactively prompt for the SYS AS SYSDBA password.

Expected output when finished:

INFO  Installing Oracle REST Data Services version 25.x.x...
INFO  ... Verified database prerequisites
INFO  ... Created Oracle REST Data Services proxy user
INFO  ... Created Oracle REST Data Services schema
INFO  ... Granted privileges to Oracle REST Data Services
INFO  ... Created Oracle REST Data Services database objects
INFO  Completed installation for Oracle REST Data Services version 25.x.x
      Elapsed time: 00:25:XX.XXX

⚠️ Important: If the command fails with the --admin-user flag, use interactive mode:

ords --config /u02/app/ords/config install --interactive \
  --log-folder /u02/app/ords/log

4.6 Configure ORDS Parameters

Once installed, configure the additional parameters needed for correct operation with APEX and the Load Balancer.

export JAVA_HOME=/u01/java/jdk-17
export ORDS_HOME=/u02/app/ords
export PATH=$JAVA_HOME/bin:$ORDS_HOME/bin:$PATH

# Enable Load Balancer header support (required for VIP)
ords --config /u02/app/ords/config config set proxy.forwardedHeaders true

# Configure listening port
ords --config /u02/app/ords/config config set standalone.http.port 8080

# Configure APEX static images path
ords --config /u02/app/ords/config config set standalone.static.path /u02/app/ords/apex_images

# Configure access log directory
ords --config /u02/app/ords/config config set standalone.access.log /u02/app/ords/log

# Verify complete configuration
ords --config /u02/app/ords/config config list

Verify that pool.xml contains the correct values:

cat /u02/app/ords/config/databases/default/pool.xml

Key values must be:

<entry key="db.connectionType">basic</entry>
<entry key="db.hostname">db-scan.mycompany.com</entry>
<entry key="db.port">1521</entry>
<entry key="db.servicename">APPDB</entry>
<entry key="db.username">ORDS_PUBLIC_USER</entry>
<entry key="plsql.gateway.mode">proxied</entry>
<entry key="proxy.forwardedHeaders">true</entry>

4.7 Foreground Startup Test

Before configuring the systemd service, verify that ORDS starts correctly in the foreground.

export JAVA_HOME=/u01/java/jdk-17
export ORDS_HOME=/u02/app/ords
export PATH=$JAVA_HOME/bin:$ORDS_HOME/bin:$PATH

ords --config /u02/app/ords/config serve \
  --port 8080 \
  --apex-images /u02/app/ords/apex_images

Expected output:

INFO  HTTP and HTTP/2 cleartext listening on host: 0.0.0.0 port: 8080
INFO  Mapped local pools from /u02/app/ords/config/databases:
  /ords/ => default => VALID
INFO  Oracle REST Data Services initialized
      Oracle REST Data Services version : 25.x.x.rXXXXXXX
      Oracle REST Data Services server info: jetty/12.x.xx

✅ The pool must appear as VALID. If it appears as INVALID, check database connectivity before proceeding.

Stop with Ctrl+C and proceed to the next step.


5. Installation on Node 2

Installation on Node 2 is similar to Node 1 with one important difference: the ORDS schema was already installed in the database in step 4.5, so it must not be executed again.

5.1 Copy Binaries from Node 1

Instead of downloading and extracting again, copy the binaries directly from Node 1. This ensures both nodes use exactly the same version.

# Execute on app-node2 as oracle
mkdir -p /u02/app/ords

# Copy ORDS binaries from Node 1
scp -r oracle@app-node1:/u02/app/ords/bin      /u02/app/ords/
scp -r oracle@app-node1:/u02/app/ords/lib      /u02/app/ords/
scp    oracle@app-node1:/u02/app/ords/ords.war  /u02/app/ords/

# Verify the binary exists and has permissions
ls -la /u02/app/ords/bin/ords
chmod +x /u02/app/ords/bin/ords

5.2 Copy Configuration and Images from Node 1

# Copy ORDS configuration (pool.xml, settings, etc.)
scp -r oracle@app-node1:/u02/app/ords/config /u02/app/ords/

# Copy APEX static images
scp -r oracle@app-node1:/u02/app/ords/apex_images /u02/app/ords/

# Create logs and bin directories
mkdir -p /u02/app/ords/log
mkdir -p /u02/app/ords/bin

5.3 Verify ORDS on Node 2

export JAVA_HOME=/u01/java/jdk-17
export ORDS_HOME=/u02/app/ords
export PATH=$JAVA_HOME/bin:$ORDS_HOME/bin:$PATH

# Verify version
ords --version

# Foreground startup test
ords --config /u02/app/ords/config serve \
  --port 8080 \
  --apex-images /u02/app/ords/apex_images

Verify the pool appears as VALID and stop with Ctrl+C.


6. Configuration as a systemd Service

Configuring ORDS as an OS service ensures it starts automatically at server boot and restarts in case of failure. This process must be performed on both nodes.

6.1 Create Startup Script

The script encapsulates the environment variables needed for systemd to start ORDS correctly.

# Execute as oracle user on each node
cat > /u02/app/ords/bin/start_ords.sh << 'EOF'
#!/bin/bash
export JAVA_HOME=/u01/java/jdk-17
export ORDS_HOME=/u02/app/ords
export PATH=$JAVA_HOME/bin:$ORDS_HOME/bin:$PATH

$ORDS_HOME/bin/ords \
  --config /u02/app/ords/config serve \
  --port 8080 \
  --apex-images /u02/app/ords/apex_images \
  >> /u02/app/ords/log/ords.log 2>&1
EOF

chmod +x /u02/app/ords/bin/start_ords.sh

6.2 Create the systemd Service File

This step requires root privileges.

# Execute as root on each node
cat > /etc/systemd/system/ords.service << 'EOF'
[Unit]
Description=Oracle REST Data Services
After=network.target

[Service]
Type=simple
User=oracle
ExecStart=/u02/app/ords/bin/start_ords.sh
ExecStop=/bin/kill -15 $MAINPID
Restart=on-failure
RestartSec=10
StandardOutput=append:/u02/app/ords/log/ords.log
StandardError=append:/u02/app/ords/log/ords.log

[Install]
WantedBy=multi-user.target
EOF

6.3 Configure Log Directory Permissions

# Execute as root on each node
mkdir -p /u02/app/ords/log
chown -R oracle:oinstall /u02/app/ords/log

6.4 Enable and Start the Service

# Execute as root on each node
systemctl daemon-reload
systemctl enable ords
systemctl start ords

# Wait for initialization and verify status
sleep 5
systemctl status ords

Expected output:

● ords.service - Oracle REST Data Services
   Loaded: loaded (/etc/systemd/system/ords.service; enabled; ...)
   Active: active (running) since [date time]
 Main PID: XXXXX (start_ords.sh)
   Memory: ~800M

6.5 Service Administration Commands

# View service status
systemctl status ords

# Stop the service
systemctl stop ords

# Restart the service
systemctl restart ords

# View logs in real time
tail -f /u02/app/ords/log/ords.log

# Verify autostart is enabled
systemctl is-enabled ords

7. Load Balancer Configuration

The Load Balancer distributes requests between the two ORDS nodes. The exact configuration depends on the LB vendor (F5, HAProxy, nginx, etc.), but the logical parameters are the same.

7.1 Required Parameters

Parameter Value
VIP / URL ords.mycompany.com
Frontend port 8080
Protocol HTTP/1.1
Backend Node 1 app-node1.mycompany.com : 8080
Backend Node 2 app-node2.mycompany.com : 8080
Algorithm Round Robin
Health Check URL GET /ords/
Health Check response HTTP 302
Session Persistence Not required — ORDS is stateless
X-Forwarded-For Header Enabled — required by ORDS

Important: ORDS is already configured to receive and process the X-Forwarded-For header via the proxy.forwardedHeaders=true parameter set in step 4.6. Ensure the LB sends it.

7.2 Verify Header Forwarding from ORDS

Once the LB is configured, verify that ORDS correctly receives the headers:

# From any external client
curl -v http://ords.mycompany.com:8080/ords/

# Verify in ORDS logs that the real client IP appears
tail -20 /u02/app/ords/log/ords.log

7.3 Zero-Downtime Go-Live Strategy

If there is an active production URL that must not be interrupted during migration, use the following strategy:

TESTING PHASE (parallel):
  Old URL → Current system (no changes)
  New URL → New VIP  → ORDS 25.x (testing)

GO-LIVE (cutover):
  Only change DNS resolution:
  Old URL → New VIP → ORDS 25.x
  Execution time: minutes
  Rollback: revert DNS

8. Environment Validation

8.1 Per-Node Validation

Execute on each node individually:

# 1. Verify service is active
systemctl status ords | grep Active

# 2. Verify port is listening
ss -tlnp | grep 8080

# 3. Verify local HTTP response
curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/ords/

# 4. Verify pool is VALID
grep "VALID" /u02/app/ords/log/ords.log | tail -5

# 5. Verify autostart is enabled
systemctl is-enabled ords

Expected results:

Active: active (running)          ← service running
LISTEN                            ← port listening
302                               ← correct HTTP response
/ords/ => default => VALID        ← pool connected to DB
enabled                           ← autostart enabled

8.2 Load Balancer Validation

# Verify access via balanced VIP
curl -v http://ords.mycompany.com:8080/ords/f?p=4550

# Expected result:
# HTTP/1.1 302 Found
# Location: http://ords.mycompany.com:8080/ords/r/apex/workspace/home

8.3 Failover Test

Verify that the LB redirects traffic when a node fails:

# 1. Stop ORDS on Node 1
systemctl stop ords   # on app-node1

# 2. Verify service is still available via VIP
curl -s -o /dev/null -w "%{http_code}" http://ords.mycompany.com:8080/ords/
# Must return 302

# 3. Restore Node 1
systemctl start ords   # on app-node1

8.4 Final Checklist

Verification Node 1 Node 2
ORDS service active
Port 8080 listening
DB pool → VALID
HTTP 302 on /ords/
Autostart enabled
Access via LB VIP
Failover test

9. Parameter Reference

9.1 pool.xml Parameters

Parameter Description Recommended Value
db.connectionType DB connection type basic
db.hostname SCAN listener hostname db-scan.mycompany.com
db.port Listener port 1521
db.servicename PDB service name APPDB
db.username ORDS connection user ORDS_PUBLIC_USER
plsql.gateway.mode PL/SQL gateway mode proxied
proxy.forwardedHeaders Enable LB headers true
restEnabledSql.active Enable REST SQL true
feature.sdw SQL Developer Web true
security.requestValidationFunction Authorization function ords_util.authorize_plsql_gateway

9.2 Standalone Parameters

Parameter Description Recommended Value
standalone.http.port HTTP listening port 8080
standalone.static.path APEX images path /u02/app/ords/apex_images
standalone.access.log Access logs directory /u02/app/ords/log

9.3 Connection Pool Sizing

⚠️ The default value of jdbc.MaxLimit is 10 connections — insufficient for production environments with high load.

# Adjust based on expected environment load
ords --config /u02/app/ords/config config set jdbc.InitialLimit 10
ords --config /u02/app/ords/config config set jdbc.MinLimit 5
ords --config /u02/app/ords/config config set jdbc.MaxLimit 30

Restart the service after changing these values:

systemctl restart ords

Guide prepared following Oracle official best practices for ORDS in production environments.
Reference: Oracle ORDS Best Practices