Skip to content
DocsTry Aspire
DocsTry

Set up PostgreSQL in the AppHost

PostgreSQL logo

This article is the reference for the Aspire PostgreSQL Hosting integration. It enumerates the AppHost APIs — with examples for both AppHost.cs and apphost.mts — that you use to model PostgreSQL server and database resources in your AppHost project.

If you’re new to the PostgreSQL integration, start with the Get started with PostgreSQL integrations guide. For how consuming apps read the connection information this page exposes, see Connect to PostgreSQL. For the PostgreSQL Entity Framework Core (EF Core) client integration, see Get started with the PostgreSQL Entity Framework Core integrations.

To start building an Aspire app that uses PostgreSQL, install the 📦 Aspire.Hosting.PostgreSQL NuGet package:

Terminal
aspire add postgres

Learn more about aspire add in the command reference.

This updates your aspire.config.json with the PostgreSQL hosting integration package:

aspire.config.json
{
"packages": {
"Aspire.Hosting.PostgreSQL": "13.5.3"
}
}

Once you’ve installed the hosting integration in your AppHost project, you can add a PostgreSQL server resource and then add a database resource as shown in the following examples:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const postgres = await builder.addPostgres("postgres");
const postgresdb = await postgres.addDatabase("postgresdb");
await builder.addNodeApp("api", "./api", "index.js")
.withReference(postgresdb);
// After adding all resources, run the app...
  1. When Aspire adds a container image to the app host, as shown in the preceding example with the docker.io/library/postgres image, it creates a new PostgreSQL server instance on your local machine. A reference to the postgresdb database resource is then used to add a dependency to the consuming project.

  2. When adding a database resource to the app model, the database is created if it doesn’t already exist. The creation of the database relies on the AppHost eventing APIs, specifically ResourceReadyEvent. In other words, when the postgres resource is ready, the event is raised and the database resource is created.

  3. The PostgreSQL server resource includes default credentials with a username of "postgres" and a randomly generated password using the CreateDefaultPasswordParameter method.

  4. The AppHost reference call configures a connection in the consuming project named after the referenced database resource, such as postgresdb in the preceding example.

  • PostgreSQL container imageDocker Hub
    docker.io/library/postgres:18.3

    Added by AddPostgres()addPostgres().

    Source

Tags reflect the latest defaults on the microsoft/aspire main branch, and may be newer than the version pinned by the package you install.

Add PostgreSQL resource with database scripts

Section titled “Add PostgreSQL resource with database scripts”

By default, when you add a PostgresDatabaseResource, it relies on the following script to create the database:

Default database creation script
CREATE DATABASE "<QUOTED_DATABASE_NAME>"

To alter the default script, configure the database resource with a custom creation script:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const postgres: PostgresServerResource
postgres
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addPostgres(name: string, options?: {
userName?: string | ParameterResource;
password?: string | ParameterResource;
port?: number;
}): PostgresServerResource (+1 overload)

Adds a PostgreSQL resource to the application model. A container is used for local development.

addPostgres
("postgres");
const
const databaseName: "app_db"
databaseName
= "app_db";
const
const creationScript: "\n-- Create the database\nCREATE DATABASE app_db;\n"
creationScript
= `
-- Create the database
CREATE DATABASE ${
const databaseName: "app_db"
databaseName
};
`;
const
const db: PostgresDatabaseResource
db
= await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.addDatabase(name: string, options?: {
databaseName?: string;
} | undefined): PostgresDatabaseResource (+1 overload)

Adds a PostgreSQL database to the application model.

addDatabase
(
const databaseName: "app_db"
databaseName
);
await
const db: PostgresDatabaseResource
db
.
PostgresDatabaseResource.withCreationScript(script: string): PostgresDatabaseResource

Defines the SQL script used to create the database.

withCreationScript
(
const creationScript: "\n-- Create the database\nCREATE DATABASE app_db;\n"
creationScript
);
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("api", "./api", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const db: PostgresDatabaseResource
db
)
.
ExecutableResource.waitFor(dependency: IResource | IResourceWithConnectionString, waitBehavior?: WaitBehavior): NodeAppResource

Waits for another resource to be ready

waitFor
(
const db: PostgresDatabaseResource
db
);
// After adding all resources, run the app...

The preceding example creates a database named app_db. The script is run when the database resource is created. The script is passed as a string to the database resource’s creation-script API and then run in the context of the PostgreSQL resource.

Add the dpage/pgadmin4 container to the PostgreSQL resource to get a web-based admin dashboard, as shown in the following examples:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const postgres: PostgresServerResource
postgres
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addPostgres(name: string, options?: {
userName?: string | ParameterResource;
password?: string | ParameterResource;
port?: number;
}): PostgresServerResource (+1 overload)

Adds a PostgreSQL resource to the application model. A container is used for local development.

addPostgres
("postgres");
await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.withPgAdmin(options?: {
configureContainer?: ((obj: PgAdminContainerResource) => Promise<void>) | undefined;
containerName?: string;
} | undefined): PostgresServerResource (+1 overload)

Adds a pgAdmin 4 administration and development platform for PostgreSQL to the application model.

withPgAdmin
();
const
const postgresdb: PostgresDatabaseResource
postgresdb
= await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.addDatabase(name: string, options?: {
databaseName?: string;
} | undefined): PostgresDatabaseResource (+1 overload)

Adds a PostgreSQL database to the application model.

addDatabase
("postgresdb");
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("api", "./api", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const postgresdb: PostgresDatabaseResource
postgresdb
);
// After adding all resources, run the app...

The preceding code adds a container based on the docker.io/dpage/pgadmin4 image. The container is used to manage the PostgreSQL server and database resources and serves a web-based admin dashboard for PostgreSQL databases.

  • pgAdmin container imageCompanion · PostgreSQLDocker Hub
    docker.io/dpage/pgadmin4:9.15.0

    Added by WithPgAdmin()withPgAdmin().

    Source

Tags reflect the latest defaults on the microsoft/aspire main branch, and may be newer than the version pinned by the package you install.

To configure the host port for the pgAdmin container, configure the pgAdmin resource inside the callback as shown in the following examples:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const postgres: PostgresServerResource
postgres
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addPostgres(name: string, options?: {
userName?: string | ParameterResource;
password?: string | ParameterResource;
port?: number;
}): PostgresServerResource (+1 overload)

Adds a PostgreSQL resource to the application model. A container is used for local development.

addPostgres
("postgres");
await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.withPgAdmin(options?: {
configureContainer?: ((obj: PgAdminContainerResource) => Promise<void>) | undefined;
containerName?: string;
} | undefined): PostgresServerResource (+1 overload)

Adds a pgAdmin 4 administration and development platform for PostgreSQL to the application model.

withPgAdmin
({
configureContainer?: ((obj: PgAdminContainerResource) => Promise<void>) | undefined
configureContainer
: async
pgAdmin: PgAdminContainerResource
pgAdmin
=> {
await
pgAdmin: PgAdminContainerResource
pgAdmin
.
PgAdminContainerResource.withHostPort(port: number | null): PgAdminContainerResource

Configures the host port that the PGAdmin resource is exposed on instead of using randomly assigned port.

withHostPort
(5050);
}
});
const
const postgresdb: PostgresDatabaseResource
postgresdb
= await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.addDatabase(name: string, options?: {
databaseName?: string;
} | undefined): PostgresDatabaseResource (+1 overload)

Adds a PostgreSQL database to the application model.

addDatabase
("postgresdb");
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("api", "./api", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const postgresdb: PostgresDatabaseResource
postgresdb
);
// After adding all resources, run the app...

The preceding code adds and configures the host port for the pgAdmin container. The host port is otherwise randomly assigned.

Add the sosedoff/pgweb container to the PostgreSQL resource to get a web-based admin dashboard, as shown in the following examples:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const postgres: PostgresServerResource
postgres
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addPostgres(name: string, options?: {
userName?: string | ParameterResource;
password?: string | ParameterResource;
port?: number;
}): PostgresServerResource (+1 overload)

Adds a PostgreSQL resource to the application model. A container is used for local development.

addPostgres
("postgres");
await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.withPgWeb(options?: {
configureContainer?: ((obj: PgWebContainerResource) => Promise<void>) | undefined;
containerName?: string;
} | undefined): PostgresServerResource (+1 overload)

Adds an administration and development platform for PostgreSQL to the application model using pgweb.

withPgWeb
();
const
const postgresdb: PostgresDatabaseResource
postgresdb
= await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.addDatabase(name: string, options?: {
databaseName?: string;
} | undefined): PostgresDatabaseResource (+1 overload)

Adds a PostgreSQL database to the application model.

addDatabase
("postgresdb");
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("api", "./api", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const postgresdb: PostgresDatabaseResource
postgresdb
);
// After adding all resources, run the app...

The preceding code adds a container based on the docker.io/sosedoff/pgweb image. All registered PostgresDatabaseResource instances are used to create a configuration file per instance, and each config is bound to the pgweb container bookmark directory. For more information, see PgWeb docs: Server connection bookmarks.

  • pgweb container imageCompanion · PostgreSQLDocker Hub
    docker.io/sosedoff/pgweb:0.17.0

    Added by WithPgWeb()withPgWeb().

    Source

Tags reflect the latest defaults on the microsoft/aspire main branch, and may be newer than the version pinned by the package you install.

To configure the host port for the pgWeb container, configure the pgWeb resource inside the callback as shown in the following examples:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const postgres: PostgresServerResource
postgres
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addPostgres(name: string, options?: {
userName?: string | ParameterResource;
password?: string | ParameterResource;
port?: number;
}): PostgresServerResource (+1 overload)

Adds a PostgreSQL resource to the application model. A container is used for local development.

addPostgres
("postgres");
await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.withPgWeb(options?: {
configureContainer?: ((obj: PgWebContainerResource) => Promise<void>) | undefined;
containerName?: string;
} | undefined): PostgresServerResource (+1 overload)

Adds an administration and development platform for PostgreSQL to the application model using pgweb.

withPgWeb
({
configureContainer?: ((obj: PgWebContainerResource) => Promise<void>) | undefined
configureContainer
: async
pgWeb: PgWebContainerResource
pgWeb
=> {
await
pgWeb: PgWebContainerResource
pgWeb
.
PgWebContainerResource.withHostPort(port: number | null): PgWebContainerResource

Configures the host port that the pgweb resource is exposed on instead of using randomly assigned port.

withHostPort
(5050);
}
});
const
const postgresdb: PostgresDatabaseResource
postgresdb
= await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.addDatabase(name: string, options?: {
databaseName?: string;
} | undefined): PostgresDatabaseResource (+1 overload)

Adds a PostgreSQL database to the application model.

addDatabase
("postgresdb");
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("api", "./api", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const postgresdb: PostgresDatabaseResource
postgresdb
);
// After adding all resources, run the app...

The preceding code adds and configures the host port for the pgWeb container. The host port is otherwise randomly assigned.

Add PostgreSQL server resource with data volume

Section titled “Add PostgreSQL server resource with data volume”

Add a data volume to the PostgreSQL server resource as shown in the following examples:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const postgres: PostgresServerResource
postgres
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addPostgres(name: string, options?: {
userName?: string | ParameterResource;
password?: string | ParameterResource;
port?: number;
}): PostgresServerResource (+1 overload)

Adds a PostgreSQL resource to the application model. A container is used for local development.

addPostgres
("postgres");
await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.withDataVolume(options?: {
name?: string;
isReadOnly?: boolean;
} | undefined): PostgresServerResource (+1 overload)

Adds a named volume for the data folder to a PostgreSQL container resource.

withDataVolume
({
isReadOnly?: boolean | undefined
isReadOnly
: false });
const
const postgresdb: PostgresDatabaseResource
postgresdb
= await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.addDatabase(name: string, options?: {
databaseName?: string;
} | undefined): PostgresDatabaseResource (+1 overload)

Adds a PostgreSQL database to the application model.

addDatabase
("postgresdb");
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("api", "./api", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const postgresdb: PostgresDatabaseResource
postgresdb
);
// After adding all resources, run the app...

The data volume is used to persist the PostgreSQL server data outside the lifecycle of its container. The container data directory depends on the PostgreSQL image version: PostgreSQL 17 and earlier use /var/lib/postgresql/data, while PostgreSQL 18 and later use /var/lib/postgresql. WithDataVolume(...) selects the correct path automatically based on the configured image tag. When a name parameter isn’t provided, the name is generated at random. For more information on data volumes and details on why they’re preferred over bind mounts, see Docker docs: Volumes.

Add PostgreSQL server resource with data bind mount

Section titled “Add PostgreSQL server resource with data bind mount”

Add a data bind mount to the PostgreSQL server resource as shown in the following examples:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const postgres: PostgresServerResource
postgres
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addPostgres(name: string, options?: {
userName?: string | ParameterResource;
password?: string | ParameterResource;
port?: number;
}): PostgresServerResource (+1 overload)

Adds a PostgreSQL resource to the application model. A container is used for local development.

addPostgres
("postgres");
await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.withDataBindMount(source: string, options?: {
isReadOnly?: boolean;
} | undefined): PostgresServerResource (+1 overload)

Adds a bind mount for the data folder to a PostgreSQL container resource.

withDataBindMount
("/PostgreSQL/Data", {
isReadOnly?: boolean | undefined
isReadOnly
: false });
const
const postgresdb: PostgresDatabaseResource
postgresdb
= await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.addDatabase(name: string, options?: {
databaseName?: string;
} | undefined): PostgresDatabaseResource (+1 overload)

Adds a PostgreSQL database to the application model.

addDatabase
("postgresdb");
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("api", "./api", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const postgresdb: PostgresDatabaseResource
postgresdb
);
// After adding all resources, run the app...

Data bind mounts rely on the host machine’s filesystem to persist the PostgreSQL server data across container restarts. The data bind mount is mounted at the C:\PostgreSQL\Data on Windows (or /PostgreSQL/Data on Unix) path on the host machine in the PostgreSQL server container. For more information on data bind mounts, see Docker docs: Bind mounts.

Add PostgreSQL server resource with init bind mount

Section titled “Add PostgreSQL server resource with init bind mount”

Use initialization files to seed the PostgreSQL server. The C# AppHost exposes WithInitBindMount(...), while the TypeScript AppHost exposes withInitFiles(...).

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const postgres: PostgresServerResource
postgres
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addPostgres(name: string, options?: {
userName?: string | ParameterResource;
password?: string | ParameterResource;
port?: number;
}): PostgresServerResource (+1 overload)

Adds a PostgreSQL resource to the application model. A container is used for local development.

addPostgres
("postgres");
await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.withInitFiles(source: string): PostgresServerResource

Copies init files to a PostgreSQL container resource.

withInitFiles
("./postgres-init");
const
const postgresdb: PostgresDatabaseResource
postgresdb
= await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.addDatabase(name: string, options?: {
databaseName?: string;
} | undefined): PostgresDatabaseResource (+1 overload)

Adds a PostgreSQL database to the application model.

addDatabase
("postgresdb");
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("api", "./api", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const postgresdb: PostgresDatabaseResource
postgresdb
);
// After adding all resources, run the app...

The TypeScript AppHost doesn’t currently expose a withInitBindMount(...) API for PostgreSQL. Use withInitFiles(...) when you want to copy initialization files into the container instead.

The init bind mount relies on the host machine’s filesystem to initialize the PostgreSQL server database with the container’s init folder. This folder is used for initialization, running any executable shell scripts or .sql command files after the postgres-data folder is created. The init bind mount is mounted at the C:\PostgreSQL\Init on Windows (or /PostgreSQL/Init on Unix) path on the host machine in the PostgreSQL server container.

Add PostgreSQL server resource with parameters

Section titled “Add PostgreSQL server resource with parameters”

When you want to explicitly provide the username and password used by the container image, you can provide these credentials as parameters. Consider the following alternative examples:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const userName: ParameterResource
userName
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addParameter(name: string, options?: {
value?: string;
publishValueAsDefault?: boolean;
secret?: boolean;
}): ParameterResource (+1 overload)

Adds a parameter resource

addParameter
("username", {
secret?: boolean | undefined
secret
: true });
const
const password: ParameterResource
password
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addParameter(name: string, options?: {
value?: string;
publishValueAsDefault?: boolean;
secret?: boolean;
}): ParameterResource (+1 overload)

Adds a parameter resource

addParameter
("password", {
secret?: boolean | undefined
secret
: true });
const
const postgres: PostgresServerResource
postgres
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addPostgres(name: string, options?: {
userName?: string | ParameterResource;
password?: string | ParameterResource;
port?: number;
}): PostgresServerResource (+1 overload)

Adds a PostgreSQL resource to the application model. A container is used for local development.

addPostgres
("postgres", {
userName?: string | ParameterResource | undefined
userName
,
password?: string | ParameterResource | undefined
password
});
const
const postgresdb: PostgresDatabaseResource
postgresdb
= await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.addDatabase(name: string, options?: {
databaseName?: string;
} | undefined): PostgresDatabaseResource (+1 overload)

Adds a PostgreSQL database to the application model.

addDatabase
("postgresdb");
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("api", "./api", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const postgresdb: PostgresDatabaseResource
postgresdb
);
// After adding all resources, run the app...

By default, Aspire injects the PostgreSQL connection information using variable names derived from the resource name (for example, POSTGRESDB_URI, POSTGRESDB_HOST, POSTGRESDB_PORT). If your consuming app expects a different set of environment variable names, pass individual connection properties from the AppHost:

apphost.mts
import {
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
,
type EndpointProperty = "Url" | "Host" | "IPV4Host" | "Port" | "Scheme" | "TargetPort" | "HostAndPort" | "TlsEnabled"
const EndpointProperty: {
readonly Url: "Url";
readonly Host: "Host";
readonly IPV4Host: "IPV4Host";
readonly Port: "Port";
readonly Scheme: "Scheme";
readonly TargetPort: "TargetPort";
readonly HostAndPort: "HostAndPort";
readonly TlsEnabled: "TlsEnabled";
}

Enum Aspire.Hosting.ApplicationModel.EndpointProperty

EndpointProperty
} from './.aspire/modules/aspire.mjs';
const
const builder: IDistributedApplicationBuilder
builder
= await
function createBuilder(): IDistributedApplicationBuilder

Creates a new distributed application builder

createBuilder
();
const
const postgres: PostgresServerResource
postgres
= await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addPostgres(name: string, options?: {
userName?: string | ParameterResource;
password?: string | ParameterResource;
port?: number;
}): PostgresServerResource (+1 overload)

Adds a PostgreSQL resource to the application model. A container is used for local development.

addPostgres
("postgres");
const
const database: PostgresDatabaseResource
database
= await
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.addDatabase(name: string, options?: {
databaseName?: string;
} | undefined): PostgresDatabaseResource (+1 overload)

Adds a PostgreSQL database to the application model.

addDatabase
("myDatabase");
const
const postgresEndpoint: EndpointReference
postgresEndpoint
= await
const postgres: PostgresServerResource
postgres
.
ContainerResource.getEndpoint(name: string): EndpointReference

Gets an endpoint reference

getEndpoint
("tcp");
const
const postgresHost: EndpointReferenceExpression
postgresHost
= await
const postgresEndpoint: EndpointReference
postgresEndpoint
.
EndpointReference.property(property: EndpointProperty): EndpointReferenceExpression

Gets the specified property expression of the endpoint.

property
(
const EndpointProperty: {
readonly Url: "Url";
readonly Host: "Host";
readonly IPV4Host: "IPV4Host";
readonly Port: "Port";
readonly Scheme: "Scheme";
readonly TargetPort: "TargetPort";
readonly HostAndPort: "HostAndPort";
readonly TlsEnabled: "TlsEnabled";
}

Enum Aspire.Hosting.ApplicationModel.EndpointProperty

EndpointProperty
.
type Host: "Host"
Host
);
const
const postgresPort: EndpointReferenceExpression
postgresPort
= await
const postgresEndpoint: EndpointReference
postgresEndpoint
.
EndpointReference.property(property: EndpointProperty): EndpointReferenceExpression

Gets the specified property expression of the endpoint.

property
(
const EndpointProperty: {
readonly Url: "Url";
readonly Host: "Host";
readonly IPV4Host: "IPV4Host";
readonly Port: "Port";
readonly Scheme: "Scheme";
readonly TargetPort: "TargetPort";
readonly HostAndPort: "HostAndPort";
readonly TlsEnabled: "TlsEnabled";
}

Enum Aspire.Hosting.ApplicationModel.EndpointProperty

EndpointProperty
.
type Port: "Port"
Port
);
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.addNodeApp(name: string, appDirectory: string, scriptPath: string): NodeAppResource

Adds a node application to the application model. Node should be available on the PATH.

addNodeApp
("my-app", "./app", "index.js")
.
ExecutableResource.withReference(source: EndpointReference | string | uri, options?: {
connectionName?: string;
optional?: boolean;
name?: string;
} | undefined): NodeAppResource (+1 overload)

Adds a reference to another resource

withReference
(
const database: PostgresDatabaseResource
database
)
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): NodeAppResource

Sets an environment variable

withEnvironment
("POSTGRES_HOST",
const postgresHost: EndpointReferenceExpression
postgresHost
)
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): NodeAppResource

Sets an environment variable

withEnvironment
("POSTGRES_PORT",
const postgresPort: EndpointReferenceExpression
postgresPort
)
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): NodeAppResource

Sets an environment variable

withEnvironment
("POSTGRES_USER",
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.userNameParameter: PropertyAccessor<ParameterResource>

Gets or sets the parameter that contains the PostgreSQL server user name.

userNameParameter
)
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): NodeAppResource

Sets an environment variable

withEnvironment
("POSTGRES_PASSWORD",
const postgres: PostgresServerResource
postgres
.
PostgresServerResource.passwordParameter: PropertyAccessor<ParameterResource>

Gets or sets the parameter that contains the PostgreSQL server password.

passwordParameter
)
.
ExecutableResource.withEnvironment(name: string, value: string | IResourceWithConnectionString | IValueProvider): NodeAppResource

Sets an environment variable

withEnvironment
("POSTGRES_DATABASE", "myDatabase");
await
const builder: IDistributedApplicationBuilder
builder
.
IDistributedApplicationBuilder.build(): DistributedApplication

Builds the distributed application

build
().
DistributedApplication.run(cancellationToken?: cancellationToken): void

Runs the distributed application

run
();

Starting with Aspire 13.4, the default PostgreSQL container image used by AddPostgres is 18.3 (previously 17.6). PostgreSQL 18 changed the on-disk data layout: the official postgres image now stores cluster files under a major-version-specific subdirectory of /var/lib/postgresql (for example, /var/lib/postgresql/18/docker), whereas PostgreSQL 17 and earlier stored data directly in /var/lib/postgresql/data. For upstream details, see docker-library/postgres#1259 and docker-library/postgres#37.

WithDataVolume(...) and WithDataBindMount(...) are version-aware: Aspire chooses the container data directory from the configured image tag at the time the method is called. PostgreSQL 17 and earlier map to /var/lib/postgresql/data; PostgreSQL 18 and later map to /var/lib/postgresql.

Because of this layout change, PostgreSQL 17 data persisted with WithDataVolume(...) or WithDataBindMount(...) (Aspire 13.3 or earlier) is incompatible with PostgreSQL 18 after upgrading to Aspire 13.4. The container fails to start with an error similar to:

Error: in 18+, these Docker images are configured to store database data in a format which is compatible with "pg_ctlcluster" ... Counter to that, there appears to be PostgreSQL data in: /var/lib/postgresql

You have two ways to recover.

Section titled “Option 1: Stay on PostgreSQL 17 (recommended, no migration)”

Pin the image back to a PostgreSQL 17 tag with WithImageTag(...) before calling WithDataVolume(...). Aspire then selects the legacy /var/lib/postgresql/data path and your existing volume keeps working with no migration:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const postgres = await builder.addPostgres("pgsql");
await postgres.withImageTag("17.6");
await postgres.withDataVolume();
// After adding all resources, run the app...

Option 2: Upgrade the data volume to PostgreSQL 18

Section titled “Option 2: Upgrade the data volume to PostgreSQL 18”

Follow the official PostgreSQL upgrade documentation using pg_dumpall/restore or pg_upgrade. Always back up the volume before migrating.

If the data is disposable, you can start fresh. Stop the app, remove any container still referencing the old volume (docker volume rm fails while the volume is in use), then remove the volume so Aspire creates a new PostgreSQL 18 volume on the next run:

Terminal window
docker volume ls
docker ps -a --filter volume=<old-volume-name>
docker rm -f <container-id>
docker volume rm <old-volume-name>

For the full reference of PostgreSQL connection properties — and how consuming apps in C#, TypeScript, Python, and Go read them — see Connect to PostgreSQL.

The PostgreSQL hosting integration automatically adds a health check for the PostgreSQL server resource. The health check verifies that the PostgreSQL server is running and that a connection can be established to it.

The hosting integration relies on the 📦 AspNetCore.HealthChecks.Npgsql NuGet package.