Skip to main content Skills Marketplace Discover and explore AI skills built by the community.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Copy promptShow prompt details A direct command skips the review prompt. Inspect the source before running it.
npx skills add https://github.com/BEKO2210/Firstbrain --skill azure-postgres-tsThe command stays on one line. Scroll horizontally to inspect it before copying.
Prefer a local copy? Download the files currently available to SkillsMP.
Download Zip Downloading... name azure-postgres-ts description Connect to Azure Database for PostgreSQL Flexible Server from Node.js/TypeScript using the pg (node-postgres) package. type skill created 2026-02-27T00:00:00.000Z domain cloud-infrastructure category azure risk unknown source community tags ["skill","cloud-infrastructure","azure","postgres"]
Azure PostgreSQL for TypeScript (node-postgres)
Connect to Azure Database for PostgreSQL Flexible Server using the pg (node-postgres) package with support for password and Microsoft Entra ID (passwordless) authentication.
Installation
npm install pg @azure/identity
npm install -D @types/pg
Environment Variables
AZURE_POSTGRESQL_HOST=<server>.postgres.database.azure.com
AZURE_POSTGRESQL_DATABASE=<database>
AZURE_POSTGRESQL_PORT=5432
AZURE_POSTGRESQL_USER=<username>
AZURE_POSTGRESQL_PASSWORD=<password>
AZURE_POSTGRESQL_USER=<entra-user>@<server>
AZURE_POSTGRESQL_CLIENTID=<managed-identity-client-id>
Authentication
Option 1: Password Authentication
import { Client , Pool } from "pg" ;
const client = new Client ({
host : process.env .AZURE_POSTGRESQL_HOST ,
database : process.env .AZURE_POSTGRESQL_DATABASE ,
user : process.env .AZURE_POSTGRESQL_USER ,
password : process.env .AZURE_POSTGRESQL_PASSWORD ,
port : Number (process.env .AZURE_POSTGRESQL_PORT ) || 5432 ,
ssl : { rejectUnauthorized : true }
});
await client. ();
connect
Option 2: Microsoft Entra ID (Passwordless) - Recommended import { Client , Pool } from "pg" ;
import { DefaultAzureCredential } from "@azure/identity" ;
const credential = new DefaultAzureCredential ();
const tokenResponse = await credential.getToken (
"https://ossrdbms-aad.database.windows.net/.default"
);
const client = new Client ({
host : process.env .AZURE_POSTGRESQL_HOST ,
database : process.env .AZURE_POSTGRESQL_DATABASE ,
user : process.env .AZURE_POSTGRESQL_USER ,
password : tokenResponse.token ,
port : Number (process.env .AZURE_POSTGRESQL_PORT ) || 5432 ,
ssl : { rejectUnauthorized : true }
});
await client.connect ();
Core Workflows
1. Single Client Connection import { Client } from "pg" ;
const client = new Client ({
host : process.env .AZURE_POSTGRESQL_HOST ,
database : process.env .AZURE_POSTGRESQL_DATABASE ,
user : process.env .AZURE_POSTGRESQL_USER ,
password : process.env .AZURE_POSTGRESQL_PASSWORD ,
port : 5432 ,
ssl : { rejectUnauthorized : true }
});
try {
await client.connect ();
const result = await client.query ("SELECT NOW() as current_time" );
console .log (result.rows [0 ].current_time );
} finally {
await client.end ();
}
2. Connection Pool (Recommended for Production) import { Pool } from "pg" ;
const pool = new Pool ({
host : process.env .AZURE_POSTGRESQL_HOST ,
database : process.env .AZURE_POSTGRESQL_DATABASE ,
user : process.env .AZURE_POSTGRESQL_USER ,
password : process.env .AZURE_POSTGRESQL_PASSWORD ,
port : 5432 ,
ssl : { rejectUnauthorized : true },
max : 20 ,
idleTimeoutMillis : 30000 ,
connectionTimeoutMillis : 10000
});
const result = await pool.query ("SELECT * FROM users WHERE id = $1" , [userId]);
const client = await pool.connect ();
try {
const res1 = await client.query ("SELECT * FROM users" );
const res2 = await client.query ("SELECT * FROM orders" );
} finally {
client.release ();
}
await pool.end ();
3. Parameterized Queries (Prevent SQL Injection)
const userId = 123 ;
const email = "user@example.com" ;
const result = await pool.query (
"SELECT * FROM users WHERE id = $1" ,
[userId]
);
const result = await pool.query (
"INSERT INTO users (email, name, created_at) VALUES ($1, $2, NOW()) RETURNING *" ,
[email, "John Doe" ]
);
const ids = [1 , 2 , 3 , 4 , 5 ];
const result = await pool.query (
"SELECT * FROM users WHERE id = ANY($1::int[])" ,
[ids]
);
4. Transactions const client = await pool.connect ();
try {
await client.query ("BEGIN" );
const userResult = await client.query (
"INSERT INTO users (email) VALUES ($1) RETURNING id" ,
["user@example.com" ]
);
const userId = userResult.rows [0 ].id ;
await client.query (
"INSERT INTO orders (user_id, total) VALUES ($1, $2)" ,
[userId, 99.99 ]
);
await client.query ("COMMIT" );
} catch (error) {
await client.query ("ROLLBACK" );
throw error;
} finally {
client.release ();
}
5. Transaction Helper Function async function withTransaction<T>(
pool : Pool ,
fn : (client : PoolClient ) => Promise <T>
): Promise <T> {
const client = await pool.connect ();
try {
await client.query ("BEGIN" );
const result = await fn (client);
await client.query ("COMMIT" );
return result;
} catch (error) {
await client.query ("ROLLBACK" );
throw error;
} finally {
client.release ();
}
}
const order = await withTransaction (pool, async (client) => {
const user = await client.query (
"INSERT INTO users (email) VALUES ($1) RETURNING *" ,
["user@example.com" ]
);
const order = await client.query (
"INSERT INTO orders (user_id, total) VALUES ($1, $2) RETURNING *" ,
[user.rows [0 ].id , 99.99 ]
);
return order.rows [0 ];
});
6. Typed Queries with TypeScript import { Pool , QueryResult } from "pg" ;
interface User {
id : number ;
email : string ;
name : string ;
created_at : Date ;
}
const result : QueryResult <User > = await pool.query <User >(
"SELECT * FROM users WHERE id = $1" ,
[userId]
);
const user : User | undefined = result.rows [0 ];
async function createUser (
pool : Pool ,
email : string ,
name : string
): Promise <User > {
const result = await pool.query <User >(
"INSERT INTO users (email, name) VALUES ($1, $2) RETURNING *" ,
[email, name]
);
return result.rows [0 ];
}
Pool with Entra ID Token Refresh For long-running applications, tokens expire and need refresh:
import { Pool , PoolConfig } from "pg" ;
import { DefaultAzureCredential , AccessToken } from "@azure/identity" ;
class AzurePostgresPool {
private pool : Pool | null = null ;
private credential : DefaultAzureCredential ;
private tokenExpiry : Date | null = null ;
private config : Omit <PoolConfig , "password" >;
constructor (config : Omit <PoolConfig , "password" > ) {
this .credential = new DefaultAzureCredential ();
this .config = config;
}
private async getToken (): Promise <string > {
const tokenResponse = await this .credential .getToken (
"https://ossrdbms-aad.database.windows.net/.default"
);
this .tokenExpiry = new Date (tokenResponse.expiresOnTimestamp );
return tokenResponse.token ;
}
private isTokenExpired (): boolean {
if (!this .tokenExpiry ) return true ;
return new Date () >= new Date (this .tokenExpiry .getTime () - 5 * 60 * 1000 );
}
async getPool (): Promise <Pool > {
if (this .pool && !this .isTokenExpired ()) {
return this .pool ;
}
if (this .pool ) {
await this .pool .end ();
}
const token = await this .getToken ();
this .pool = new Pool ({
...this .config ,
password : token
});
return this .pool ;
}
async query<T>(text : string , params ?: any []): Promise <QueryResult <T>> {
const pool = await this .getPool ();
return pool.query <T>(text, params);
}
async end (): Promise <void > {
if (this .pool ) {
await this .pool .end ();
this .pool = null ;
}
}
}
const azurePool = new AzurePostgresPool ({
host : process.env .AZURE_POSTGRESQL_HOST !,
database : process.env .AZURE_POSTGRESQL_DATABASE !,
user : process.env .AZURE_POSTGRESQL_USER !,
port : 5432 ,
ssl : { rejectUnauthorized : true },
max : 20
});
const result = await azurePool.query ("SELECT NOW()" );
Error Handling import { DatabaseError } from "pg" ;
try {
await pool.query ("INSERT INTO users (email) VALUES ($1)" , [email]);
} catch (error) {
if (error instanceof DatabaseError ) {
switch (error.code ) {
case "23505" :
console .error ("Duplicate entry:" , error.detail );
break ;
case "23503" :
console .error ("Foreign key constraint failed:" , error.detail );
break ;
case "42P01" :
console .error ("Table does not exist:" , error.message );
break ;
case "28P01" :
console .error ("Authentication failed" );
break ;
case "57P03" :
console .error ("Server unavailable, retry later" );
break ;
default :
console .error (`PostgreSQL error ${error.code} : ${error.message} ` );
}
}
throw error;
}
Connection String Format
const pool = new Pool ({
connectionString : `postgres://${user} :${password} @${host} :${port} /${database} ?sslmode=require`
});
const connectionString =
`postgres://user:password@server.postgres.database.azure.com:5432/mydb?sslmode=require` ;
Pool Events const pool = new Pool ({ });
pool.on ("connect" , (client ) => {
console .log ("New client connected to pool" );
});
pool.on ("acquire" , (client ) => {
console .log ("Client checked out from pool" );
});
pool.on ("release" , (err, client ) => {
console .log ("Client returned to pool" );
});
pool.on ("remove" , (client ) => {
console .log ("Client removed from pool" );
});
pool.on ("error" , (err, client ) => {
console .error ("Unexpected pool error:" , err);
});
Azure-Specific Configuration Setting Value Description ssl.rejectUnauthorizedtrueAlways use SSL for Azure Default port 5432Standard PostgreSQL port PgBouncer port 6432Use when PgBouncer enabled Token scope https://ossrdbms-aad.database.windows.net/.defaultEntra ID token scope Token lifetime ~1 hour Refresh before expiry
Pool Sizing Guidelines Workload maxidleTimeoutMillisLight (dev/test) 5-10 30000 Medium (production) 20-30 30000 Heavy (high concurrency) 50-100 10000
Note : Azure PostgreSQL has connection limits based on SKU. Check your tier's max connections.
Best Practices
Always use connection pools for production applications
Use parameterized queries - Never concatenate user input
Always close connections - Use try/finally or connection pools
Enable SSL - Required for Azure (ssl: { rejectUnauthorized: true })
Handle token refresh - Entra ID tokens expire after ~1 hour
Set connection timeouts - Avoid hanging on network issues
Use transactions - For multi-statement operations
Monitor pool metrics - Track pool.totalCount, pool.idleCount, pool.waitingCount
Graceful shutdown - Call pool.end() on application termination
Use TypeScript generics - Type your query results for safety
Key Types import {
Client ,
Pool ,
PoolClient ,
PoolConfig ,
QueryResult ,
QueryResultRow ,
DatabaseError ,
QueryConfig
} from "pg" ;
Reference Links
When to Use This skill is applicable to execute the workflow or actions described in the overview.
Connections
Domain: [[Cloud & Infrastruktur]]
Kategorie: [[Microsoft Azure]]
Navigation: [[Skills Uebersicht]], [[Home]]
More from this repository
Related occupations SOC
Based on SOC occupation classification