From 245d0b1272294fc2812276e7c8f2413574ec73e1 Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Sun, 8 Feb 2026 23:45:48 +0530 Subject: [PATCH 1/2] docs(postgres): add IaC guides (Terraform, Pulumi, Alchemy) --- cSpell.json | 4 +- .../250-postgres/360-iac/100-terraform.mdx | 177 +++++++++++++ content/250-postgres/360-iac/200-pulumi.mdx | 165 ++++++++++++ content/250-postgres/360-iac/300-alchemy.mdx | 242 ++++++++++++++++++ content/250-postgres/360-iac/_category_.json | 5 + content/250-postgres/360-iac/index.mdx | 13 + 6 files changed, 605 insertions(+), 1 deletion(-) create mode 100644 content/250-postgres/360-iac/100-terraform.mdx create mode 100644 content/250-postgres/360-iac/200-pulumi.mdx create mode 100644 content/250-postgres/360-iac/300-alchemy.mdx create mode 100644 content/250-postgres/360-iac/_category_.json create mode 100644 content/250-postgres/360-iac/index.mdx diff --git a/cSpell.json b/cSpell.json index 0547d1441f..3348b787d4 100644 --- a/cSpell.json +++ b/cSpell.json @@ -128,7 +128,9 @@ "Treatos", "Svetlana", "Queenie", - "Linktree" + "Linktree", + "Pulumi", + "buildpack" ], "ignoreWords": [ "Aiven", diff --git a/content/250-postgres/360-iac/100-terraform.mdx b/content/250-postgres/360-iac/100-terraform.mdx new file mode 100644 index 0000000000..3cb7b30fbb --- /dev/null +++ b/content/250-postgres/360-iac/100-terraform.mdx @@ -0,0 +1,177 @@ +--- +title: 'Terraform' +metaTitle: 'Manage Prisma Postgres with Terraform' +metaDescription: 'Provision and manage Prisma Postgres projects, databases, and connections using Terraform.' +tocDepth: 3 +toc: true +--- + +Use the [Prisma Postgres Terraform provider](https://registry.terraform.io/providers/prisma/prisma-postgres/latest) to manage projects, databases, and connections with code. + +## Conceptual model + +Terraform is a desired-state engine: + +- You declare the target infrastructure in `.tf` files. +- Terraform computes a plan (`terraform plan`) by comparing config vs current state. +- Terraform applies only the required changes (`terraform apply`) and records the result in state. + +For Prisma Postgres, this gives a predictable workflow for creating projects, databases, and connections across environments. + +## When to use Terraform + +Terraform is a strong fit when: + +- You already manage infrastructure in Terraform and want one workflow. +- You prefer explicit `plan` output before applying changes. +- Your team standardizes on HCL modules and Terraform state backends. + +## What you can manage + +The provider currently supports: + +- `prisma-postgres_project` +- `prisma-postgres_database` +- `prisma-postgres_connection` +- `prisma-postgres_regions` data source + +## Prerequisites + +- [Terraform](https://developer.hashicorp.com/terraform/install) `>= 1.0` +- A Prisma account and workspace in [Prisma Console](https://console.prisma.io) +- A Prisma service token (see [Management API authentication docs](/postgres/introduction/management-api#service-tokens)) + +## 1. Set your service token + +Set your token as an environment variable: + +```terminal +export PRISMA_SERVICE_TOKEN="prsc_your_token_here" +``` + +## 2. Create `main.tf` + +Create the following Terraform configuration: + +```hcl file=main.tf +terraform { + required_providers { + prisma-postgres = { + source = "prisma/prisma-postgres" + } + } +} + +provider "prisma-postgres" {} + +resource "prisma-postgres_project" "main" { + name = "my-app" +} + +resource "prisma-postgres_database" "production" { + project_id = prisma-postgres_project.main.id + name = "production" + region = "us-east-1" +} + +resource "prisma-postgres_connection" "api" { + database_id = prisma-postgres_database.production.id + name = "api-key" +} + +output "connection_string" { + value = prisma-postgres_connection.api.connection_string + sensitive = true +} + +output "direct_url" { + value = prisma-postgres_database.production.direct_url + sensitive = true +} +``` + +## 3. Initialize and apply + +Initialize your working directory: + +```terminal +terraform init +``` + +Review and apply: + +```terminal +terraform plan +terraform apply +``` + +After apply, retrieve values: + +```terminal +terraform output -raw connection_string +terraform output -raw direct_url +``` + +## 4. Clean up (optional) + +```terminal +terraform destroy +``` + +## Optional: discover available regions + +If you want to select regions dynamically: + +```hcl +data "prisma-postgres_regions" "available" {} + +output "available_regions" { + value = [ + for r in data.prisma-postgres_regions.available.regions : "${r.id} (${r.name})" + if r.status == "available" + ] +} +``` + +## Production notes + +- Store Terraform state in a secure remote backend (for example, S3 + DynamoDB, Terraform Cloud, etc.). +- Treat state as sensitive: even with `sensitive = true`, secret values are still stored in state. +- Keep `PRISMA_SERVICE_TOKEN` in your secret manager or CI secrets, not in code. +- Use separate Terraform workspaces or stacks for `dev`, `staging`, and `prod`. +- Rotate credentials intentionally when required by replacing connection resources. + +## Import existing resources + +You can import existing resources into state: + +```terminal +terraform import prisma-postgres_project.main +terraform import prisma-postgres_database.production +terraform import prisma-postgres_connection.api , +``` + +Credentials are only returned at creation time and cannot be recovered after import. + +## Common troubleshooting + +### Missing token + +If provider configuration fails with a missing token error, confirm `PRISMA_SERVICE_TOKEN` is set in the same shell session running Terraform. + +### Region issues + +If create fails for a region value, use `prisma-postgres_regions` to list currently available regions for your workspace. + +### Authorization failures + +If you receive authorization errors, verify your service token belongs to the expected workspace and has permission to create projects and databases. + +## References + +- [Prisma Postgres provider on Terraform Registry](https://registry.terraform.io/providers/prisma/prisma-postgres/latest) +- [Provider configuration](https://registry.terraform.io/providers/prisma/prisma-postgres/latest/docs) +- [Project resource](https://registry.terraform.io/providers/prisma/prisma-postgres/latest/docs/resources/project) +- [Database resource](https://registry.terraform.io/providers/prisma/prisma-postgres/latest/docs/resources/database) +- [Connection resource](https://registry.terraform.io/providers/prisma/prisma-postgres/latest/docs/resources/connection) +- [Regions data source](https://registry.terraform.io/providers/prisma/prisma-postgres/latest/docs/data-sources/regions) diff --git a/content/250-postgres/360-iac/200-pulumi.mdx b/content/250-postgres/360-iac/200-pulumi.mdx new file mode 100644 index 0000000000..db2fc000ce --- /dev/null +++ b/content/250-postgres/360-iac/200-pulumi.mdx @@ -0,0 +1,165 @@ +--- +title: 'Pulumi' +metaTitle: 'Manage Prisma Postgres with Pulumi' +metaDescription: 'Provision and manage Prisma Postgres with Pulumi using the Prisma Terraform provider bridge.' +tocDepth: 3 +toc: true +--- + +Use Pulumi with the Prisma Postgres Terraform provider through the Pulumi Terraform bridge. + +This is the currently supported path for managing Prisma Postgres from Pulumi. + +## Conceptual model + +Pulumi lets you define infrastructure with a general-purpose language, but still deploys declaratively: + +- You write resource code in TypeScript. +- Pulumi builds a dependency graph and previews changes (`pulumi preview`/`pulumi up`). +- Stack state tracks what exists, including secret outputs. + +In this guide, Pulumi consumes the Prisma Terraform provider through a generated SDK, so you get typed resources while reusing the same provider capabilities. + +## When to use Pulumi + +Pulumi is a strong fit when: + +- You want infrastructure and application code in the same language. +- You prefer typed APIs and IDE support over HCL. +- You already use Pulumi stacks for environment management. + +## Prerequisites + +- [Pulumi CLI](https://www.pulumi.com/docs/iac/download-install/) +- A Pulumi TypeScript project (create one with `pulumi new typescript`) +- A Prisma service token (see [Management API authentication docs](/postgres/introduction/management-api#service-tokens)) + +## 1. Optional: use Bun for dependency installs + +If you want Pulumi to use Bun in this project, set this in `Pulumi.yaml`: + +```yaml file=Pulumi.yaml +runtime: + name: nodejs + options: + packagemanager: bun +``` + +## 2. Add the Prisma Postgres provider package + +From your Pulumi project directory, run: + +```terminal +pulumi package add terraform-provider registry.terraform.io/prisma/prisma-postgres 0.2.0 +``` + +This command: + +- Generates a local SDK in `sdks/prisma-postgres` +- Adds `packages.prisma-postgres` metadata to `Pulumi.yaml` +- Adds `@pulumi/prisma-postgres` to `package.json` as a local file dependency + +### Alternative: local provider binary + +If you are developing the provider locally, you can also add it from a local binary path: + +```terminal +pulumi package add terraform-provider /absolute/path/to/terraform-provider-prisma-postgres +``` + +For most users, the registry form in step 2 is the recommended approach. + +## 3. Configure authentication + +Use one of these methods: + +### Option A: environment variable + +```terminal +export PRISMA_SERVICE_TOKEN="prsc_your_token_here" +``` + +### Option B: Pulumi config secret + +```terminal +pulumi config set prisma-postgres:serviceToken "prsc_your_token_here" --secret +``` + +## 4. Define resources in `index.ts` + +```ts file=index.ts +import * as pulumi from "@pulumi/pulumi"; +import * as prismaPostgres from "@pulumi/prisma-postgres"; + +const project = new prismaPostgres.Project("project", { + name: "my-app", +}); + +const database = new prismaPostgres.Database("database", { + projectId: project.id, + name: "production", + region: "us-east-1", +}); + +const connection = new prismaPostgres.Connection("connection", { + databaseId: database.id, + name: "api-key", +}); + +const availableRegions = prismaPostgres.getRegionsOutput().regions.apply((regions) => + regions.filter((r) => r.status === "available").map((r) => `${r.id} (${r.name})`) +); + +export const projectId = project.id; +export const databaseId = database.id; +export const connectionString = pulumi.secret(connection.connectionString); +export const directUrl = pulumi.secret(database.directUrl); +export const regions = availableRegions; +``` + +## 5. Deploy + +```terminal +pulumi up +``` + +To read secret outputs: + +```terminal +pulumi stack output connectionString --show-secrets +pulumi stack output directUrl --show-secrets +``` + +## 6. Clean up + +```terminal +pulumi destroy +``` + +## Production notes + +- Store Pulumi state in a managed backend (Pulumi Cloud, S3-compatible backend, etc.). +- Keep service tokens in Pulumi secrets/config or your secret manager, never in source files. +- The generated SDK is a local dependency (`file:sdks/prisma-postgres`), so keep it available in CI/CD. +- Pin the Terraform provider version in `pulumi package add` for reproducible deployments. + +## Common troubleshooting + +### Package add failed + +Confirm you're running the command inside a Pulumi project directory containing `Pulumi.yaml`. + +### Missing credentials + +If provider auth fails, verify either `PRISMA_SERVICE_TOKEN` is set or `prisma-postgres:serviceToken` is configured for the current stack. + +### SDK not found in CI + +If CI cannot resolve `@pulumi/prisma-postgres`, make sure `sdks/prisma-postgres` exists in the workspace or rerun `pulumi package add` during CI setup. + +## References + +- [Pulumi package add](https://www.pulumi.com/docs/iac/cli/commands/pulumi_package_add/) +- [Using any Terraform provider in Pulumi](https://www.pulumi.com/docs/iac/concepts/providers/any-terraform-provider/) +- [Prisma Postgres provider on Terraform Registry](https://registry.terraform.io/providers/prisma/prisma-postgres/latest) +- [Prisma Postgres Terraform provider source](https://github.com/prisma/terraform-provider-prisma-postgres) diff --git a/content/250-postgres/360-iac/300-alchemy.mdx b/content/250-postgres/360-iac/300-alchemy.mdx new file mode 100644 index 0000000000..3b7c9977df --- /dev/null +++ b/content/250-postgres/360-iac/300-alchemy.mdx @@ -0,0 +1,242 @@ +--- +title: 'Alchemy' +metaTitle: 'Manage Prisma Postgres with Alchemy' +metaDescription: 'Provision and manage Prisma Postgres projects, databases, and connections with Alchemy.' +tocDepth: 3 +toc: true +--- + +Use [Alchemy](https://alchemy.run) to manage Prisma Postgres resources directly in your infrastructure code. + +Alchemy provides Prisma Postgres resources for: + +- Projects +- Databases +- Connections +- Workspace references + +## Conceptual model + +Alchemy is a TypeScript library that creates and manages infrastructure when you run it. + +Instead of a separate declarative config format, you write a normal TypeScript program (commonly `alchemy.run.ts`) and execute it. + +Alchemy resources follow lifecycle phases (`create`, `update`, `delete`) and manage provider APIs for you: + +- You compose resources in code (`Project`, `Database`, `Connection`). +- Alchemy handles dependency ordering between those resources. +- Resource defaults can include safety behavior, such as delete protection on projects and databases. +- `await app.finalize()` cleans up orphaned resources that are no longer in your program. + +This makes it useful when you want infrastructure code that feels close to your application runtime and platform integrations. + +## When to use Alchemy + +Alchemy is a strong fit when: + +- You are already deploying with Alchemy and want Prisma Postgres in the same graph. +- You want resource composition with first-class platform integrations (for example, Hyperdrive + Workers). +- You prefer lifecycle-driven resource code with safe deletion defaults. + +## Typical workflow + +If you follow the Alchemy getting started flow, the common lifecycle is: + +```terminal +# create project scaffold (optional) +bunx alchemy@latest create --template typescript + +# configure provider profiles/credentials +bun alchemy configure + +# authenticate (required for Cloudflare resources) +bun alchemy login + +# local development with hot reload +bun alchemy dev + +# deploy +bun alchemy deploy + +# tear down +bun alchemy destroy +``` + +For Prisma Postgres-only resources, `configure`/`login` may not be necessary in every setup. They are typically needed when you also manage Cloudflare resources in the same app. + +For script execution, Alchemy also supports direct Bun/Node execution equivalents documented in the "What is Alchemy?" page. + +## Prerequisites + +- An Alchemy project +- A Prisma service token +- `PRISMA_SERVICE_TOKEN` configured in your environment +- `ALCHEMY_PASSWORD` configured when your resources contain secrets + +## Authentication + +Alchemy reads Prisma credentials from environment variables by default. + +```terminal +export PRISMA_SERVICE_TOKEN="prsc_your_token_here" +export ALCHEMY_PASSWORD="choose-a-strong-password" +``` + +If you need multiple workspaces/accounts, you can override auth per resource with `serviceToken`. + +`ALCHEMY_PASSWORD` is used to encrypt/decrypt secret values in Alchemy state. + +## Minimal example + +```ts file=alchemy.run.ts +import alchemy from "alchemy"; +import { Connection, Database, Project } from "alchemy/prisma-postgres"; + +const app = await alchemy("prisma-postgres-example"); + +const project = await Project("project"); + +const database = await Database("database", { + project, + region: "us-east-1", +}); + +const connection = await Connection("connection", { + database, + name: "app-connection", +}); + +export const projectId = project.id; +export const databaseId = database.id; +export const host = connection.host; +export const user = connection.user; +export const connectionString = connection.connectionString; +export const prismaConnectionString = connection.prismaConnectionString; + +await app.finalize(); +``` + +## Complete example with Hyperdrive + Worker + +```ts file=alchemy.run.ts +import alchemy from "alchemy"; +import { Hyperdrive, Worker } from "alchemy/cloudflare"; +import { Connection, Database, Project } from "alchemy/prisma-postgres"; + +const app = await alchemy("prisma-postgres-example"); + +const project = await Project("project"); + +const database = await Database("database", { + project, + region: "us-east-1", +}); + +const connection = await Connection("connection", { + database, + name: "connection", +}); + +const db = await Hyperdrive("prisma-postgres", { + origin: connection.connectionString.unencrypted, +}); + +export const worker = await Worker("worker", { + entrypoint: "src/worker.ts", + bindings: { + HYPERDRIVE: db, + }, + compatibilityFlags: ["nodejs_compat"], +}); + +await app.finalize(); +``` + +```ts file=src/worker.ts +import { Client } from "pg"; +import type { worker } from "../alchemy.run.ts"; + +export default { + async fetch(_request: Request, env: typeof worker.Env): Promise { + const client = new Client({ + connectionString: env.HYPERDRIVE.connectionString, + }); + + try { + await client.connect(); + const result = await client.query("SELECT * FROM pg_tables"); + + return Response.json({ + success: true, + result: result.rows, + }); + } catch (error: any) { + return new Response(`Database error: ${error.message}`, { status: 500 }); + } + }, +}; +``` + +## Working with multiple workspaces + +Prisma service tokens are workspace-scoped. You can pass different tokens to different resources: + +```ts +import alchemy from "alchemy"; +import { Project } from "alchemy/prisma-postgres"; + +const app = await alchemy("prisma-workspaces"); + +const workspaceAProject = await Project("workspace-a-project", { + serviceToken: alchemy.env.PRISMA_SERVICE_TOKEN_WORKSPACE_A, +}); + +const workspaceBProject = await Project("workspace-b-project", { + serviceToken: alchemy.env.PRISMA_SERVICE_TOKEN_WORKSPACE_B, +}); + +await app.finalize(); +``` + +If you need to resolve a workspace by name or id, use `WorkspaceRef`: + +```ts +import { WorkspaceRef } from "alchemy/prisma-postgres"; + +const workspace = await WorkspaceRef("my-workspace"); +``` + +## Deletion behavior + +`Project` and `Database` default to delete protection in Alchemy. + +- `Project`: `delete` defaults to `false` +- `Database`: `delete` defaults to `false` + +For ephemeral environments, set `delete: true` explicitly: + +```ts +const testDatabase = await Database("test-db", { + project, + region: "us-east-1", + delete: true, +}); +``` + +## Common troubleshooting + +### Missing token + +If resource creation fails with an auth error, confirm `PRISMA_SERVICE_TOKEN` is set for the process running Alchemy. + +### Wrong workspace + +Prisma service tokens are workspace-scoped. If resources appear in the wrong workspace, use per-resource `serviceToken` overrides. + +## References + +- [Alchemy](https://alchemy.run) +- [Alchemy getting started](https://alchemy.run/getting-started) +- [What is Alchemy?](https://alchemy.run/what-is-alchemy/) +- [Alchemy package on npm](https://www.npmjs.com/package/alchemy) +- [Prisma Postgres](https://www.prisma.io/postgres) diff --git a/content/250-postgres/360-iac/_category_.json b/content/250-postgres/360-iac/_category_.json new file mode 100644 index 0000000000..7a002261ab --- /dev/null +++ b/content/250-postgres/360-iac/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "IaC", + "collapsible": false, + "collapsed": false +} diff --git a/content/250-postgres/360-iac/index.mdx b/content/250-postgres/360-iac/index.mdx new file mode 100644 index 0000000000..488f383adb --- /dev/null +++ b/content/250-postgres/360-iac/index.mdx @@ -0,0 +1,13 @@ +--- +title: 'IaC' +sidebar_label: 'IaC' +metaTitle: 'Infrastructure as Code for Prisma Postgres' +metaDescription: 'Manage Prisma Postgres with Infrastructure as Code tools like Terraform, Pulumi, and Alchemy.' +hide_table_of_contents: true +--- + +Use Infrastructure as Code to provision and manage Prisma Postgres resources in a repeatable way with tools like Terraform, Pulumi, and Alchemy. + +## In this section + + From f3ef6cf5bc0d86c5fdc963cf7368e6a25de30b3b Mon Sep 17 00:00:00 2001 From: Aman Varshney Date: Tue, 10 Feb 2026 21:13:56 +0530 Subject: [PATCH 2/2] docs(postgres): spell out Infrastructure as Code --- content/250-postgres/360-iac/_category_.json | 4 ++-- content/250-postgres/360-iac/index.mdx | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/content/250-postgres/360-iac/_category_.json b/content/250-postgres/360-iac/_category_.json index 7a002261ab..b582f25f72 100644 --- a/content/250-postgres/360-iac/_category_.json +++ b/content/250-postgres/360-iac/_category_.json @@ -1,5 +1,5 @@ { - "label": "IaC", + "label": "Infrastructure as Code", "collapsible": false, "collapsed": false -} +} \ No newline at end of file diff --git a/content/250-postgres/360-iac/index.mdx b/content/250-postgres/360-iac/index.mdx index 488f383adb..493dc16184 100644 --- a/content/250-postgres/360-iac/index.mdx +++ b/content/250-postgres/360-iac/index.mdx @@ -1,12 +1,12 @@ --- -title: 'IaC' -sidebar_label: 'IaC' +title: 'Infrastructure as Code' +sidebar_label: 'Infrastructure as Code' metaTitle: 'Infrastructure as Code for Prisma Postgres' metaDescription: 'Manage Prisma Postgres with Infrastructure as Code tools like Terraform, Pulumi, and Alchemy.' hide_table_of_contents: true --- -Use Infrastructure as Code to provision and manage Prisma Postgres resources in a repeatable way with tools like Terraform, Pulumi, and Alchemy. +Use Infrastructure as Code (IaC) to provision and manage Prisma Postgres resources in a repeatable way with tools like Terraform, Pulumi, and Alchemy. ## In this section