cancel
Showing results for 
Search instead for 
Did you mean: 

Private Link + CAP + PostgreSQL on AWS

08-04-2026 7:51 PM
fabi2295 Participant
182 views 3 comments Go to solution
SAP Managed Tags
Subscribe

Hi.

I have a private link set up pointing to a PostgreSQL database running on AWS. The private link service itself is already provisioned and configured on the BTP side. What I need to understand is how to wire this up properly in a CAP Node.js project.

Does @cap-js/postgres automatically route queries through the private link once the service is bound to the app, or does it need additional configuration to know it should use that network path?

I also added the private link service as a requires entry in the SRV module inside mta.yaml, so the binding is there at runtime. But I am not sure if that alone is enough for CAP to pick up the database connection through it, since there is no standard PostgreSQL service instance, just the private link binding exposing the endpoint.

Is binding it in mta.yaml the right approach, or is there something else needed on the CAP or adapter level to make this work end to end?

server.js

fabi2295_1-1785865725125.png

mta

fabi2295_2-1785865769863.png

Requires SRV with private link 

fabi2295_3-1785865842598.png

package.json

fabi2295_0-1785865654856.png

 

#privatelink #btp #capnodejs #cap #postgres #postgresoncap

Accepted Solutions (1)

Accepted Solutions (1)

fabi2295
Participant

Hello @Willem_Pardaens 

I did it this way and it worked.

1. Add the Private Link Service Binding

In your mta.yaml, add the Private Link service instance as a resource and bind it to your CAP service module:

modules:
- name: your-cap-srv
  requires:
  - name: my-privatelink-postgres

resources:
- name: my-privatelink-postgres
  type: org.cloudfoundry.existing-service
 

This binding makes the Private Link credentials available inside VCAP_SERVICES at runtime, under the privatelink key.


2. Install the PostgreSQL adapter

cds add postgres --for production

and

npm install

3. Configure cds.requires in package.json

Set the database kind to postgres. Credentials will be injected at runtime via server.js:

{
      "[production]": {
        "db": {
          "kind": "postgres"
        }
      },
}
 

4. Create server.js

At the root of your CAP project, create a server.js file. It reads the Private Link hostname from VCAP_SERVICES and the remaining credentials from User-Provided Variables, then injects everything into cds.env.requires.db before the app starts:

"use strict";

const cds = require("@sap/cds");

cds.on("bootstrap", (app) => {
  const LOG = cds.log("server");

  if (process.env.VCAP_SERVICES) {
    const vcap = JSON.parse(process.env.VCAP_SERVICES);
    const pl = (vcap["privatelink"] || []).find(
      (s) => s.name === "ipp-privatelink-dev"
    );
  
    if (pl?.credentials?.hostname) {
      cds.env.requires.db = cds.env.requires.db || {};
      cds.env.requires.db.credentials = {
        host: pl.credentials.hostname,
        port: Number(process.env.DB_PORT),
        user: process.env.DB_USER,
        password: process.env.DB_PASSWORD,
        database: process.env.DB_DATABASE,
        schema: process.env.DB_SCHEMA,
        ssl: { rejectUnauthorized: false },
      };
    }
  } else {
    LOG.info("[DB] VCAP_SERVICES não presente — ambiente local (SQLite)");
  }
});
 
 
The host is not set manually — it comes from the Private Link binding credential (pl.credentials.hostname). All other values come from environment variables, keeping secrets out of source code.

5. Set the User-Provided Variables in BTP Cockpit

Go to your application in BTP Cockpit → User-Provided Variables and create the following entries:

Variable Description
PL_SERVICE_NAMEName of the Private Link service instance (e.g. privatelink)
DB_PORTPostgreSQL port, typically 5432
DB_USERDatabase user
DB_PASSWORDDatabase password
DB_DATABASEDatabase name
DB_SCHEMASchema name (e.g. public)

The variable names do not need to match exactly  they just need to be consistent with what process.env.<VARIABLE_NAME> reads in server.js.

After adding or changing any variable, restart the application for the changes to take effect:

 
cf restart <your-app-name>

 

Answers (1)

Answers (1)

fabi2295
Participant
0 Likes

@Willem_Pardaens 

Thank you for the response, I'll test it and I'll come back with the answer if it works.