Skip to content

feat: add Prisma provider#416

Open
AmanVarshney01 wants to merge 123 commits into
alchemy-run:mainfrom
AmanVarshney01:aman/prisma-alchemy-provider
Open

feat: add Prisma provider#416
AmanVarshney01 wants to merge 123 commits into
alchemy-run:mainfrom
AmanVarshney01:aman/prisma-alchemy-provider

Conversation

@AmanVarshney01

@AmanVarshney01 AmanVarshney01 commented May 22, 2026

Copy link
Copy Markdown

Prisma provider

This PR introduces the first production-grade Prisma provider for Alchemy.

It adds declarative resources for Prisma Postgres and Prisma Compute, aligns the provider with the current Prisma Management API, and supports both framework applications and Effect-native services. Resources reconcile from observed API state, recover safely from interrupted deployments, and avoid persisting Prisma credentials as plaintext.

Quick start

import * as Alchemy from "alchemy";
import * as Cloudflare from "alchemy/Cloudflare";
import * as Prisma from "alchemy/Prisma";
import * as Effect from "effect/Effect";

export default Alchemy.Stack(
  "PrismaApp",
  {
    providers: Prisma.providers(),
    state: Cloudflare.state(),
  },
  Effect.gen(function* () {
    const project = yield* Prisma.Project("Project", {
      createDatabase: false,
      region: "eu-west-3",
    });

    const postgres = yield* Prisma.Postgres("Postgres", {
      project,
      region: "eu-west-3",
      branchGitName: "main",
    });

    const connection = yield* Prisma.Connection("Connection", {
      database: postgres,
      name: "web",
    });

    const app = yield* Prisma.Compute("App", {
      project,
      appName: "my-prisma-app",
      regionId: "eu-west-3",
      branchGitName: "main",
      path: "./app",
      build: {
        command: "bun run build",
        outdir: ".output",
        entrypoint: "server/index.mjs",
      },
      port: 3000,
      healthCheck: {
        path: "/api/health",
      },
      env: Prisma.connectionEnv(connection),
      destroyOldDeployment: true,
    });

    return {
      projectId: project.projectId,
      databaseId: postgres.databaseId,
      url: app.url,
    };
  }),
);

Provider surface

API Purpose
Project Creates and manages a Prisma project
Database / Postgres Manages Prisma Postgres databases
Branch Manages database branches
Connection Creates named database connections and exposes redacted connection outputs
App Manages Prisma Compute applications
Deployment Manages individual Compute deployment artifacts and lifecycle
Compute Builds, uploads, deploys, promotes, verifies, and replaces an application
EnvironmentVariable Manages Compute environment variables
CustomDomain Manages custom domains
SourceRepository Connects source repositories to Prisma applications

The provider also includes Management API operations, deployment log helpers, connection helpers, and runtime bindings for Prisma Compute, AWS Lambda, and Cloudflare Workers.

Prisma Postgres

const project = yield* Prisma.Project("Project", {
  createDatabase: false,
  region: "eu-west-3",
});

const postgres = yield* Prisma.Postgres("Postgres", {
  project,
  region: "eu-west-3",
  branchGitName: "main",
  dev: {
    provider: "@prisma/dev",
    migrate: "bun run db:setup",
  },
});

const connection = yield* Prisma.Connection("Connection", {
  database: postgres,
  name: "web",
});

Connection values remain typed Alchemy outputs and secret values are redacted. Applications can receive the conventional Prisma environment variables without manually extracting credentials:

const databaseEnv = Prisma.connectionEnv(connection);

// DATABASE_URL
// DIRECT_URL
// POOLED_DATABASE_URL
// PRISMA_CONNECTION_ID
// PRISMA_DATABASE_ID

const app = yield* Prisma.Compute("App", {
  // ...
  env: databaseEnv,
});

A specific connection URL can also be selected explicitly:

const directUrl = Prisma.connectionUrl(connection, "direct");
const pooledUrl = Prisma.connectionUrl(connection, "pooled");

Framework applications on Prisma Compute

Compute accepts an explicit build contract or build: "auto". Automatic build detection supports Bun applications and common frameworks including Next.js, Nuxt, Astro, TanStack Start, and NestJS.

const app = yield* Prisma.Compute("Web", {
  project,
  appName: "web",
  regionId: "eu-west-3",
  branchGitName: "main",
  path: ".",
  build: {
    command: "bun run build",
    outdir: ".output",
    entrypoint: "server/index.mjs",
  },
  port: 3000,
  healthCheck: {
    path: "/api/health",
  },
  env: {
    ...Prisma.connectionEnv(connection),
    NODE_ENV: "production",
  },
  dev: {
    command: "bun run dev:start",
    port: 3000,
  },
  destroyOldDeployment: true,
});

Effect-native Compute

Effect applications can be deployed directly without introducing a separate server framework. Runtime database access is provided through a typed binding:

import * as Prisma from "alchemy/Prisma";
import * as Effect from "effect/Effect";
import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";

export default Prisma.Compute(
  "Api",
  {
    project,
    appName: "api",
    main: import.meta.filename,
    port: 3000,
    healthCheck: {
      path: "/api/health",
    },
  },
  Effect.gen(function* () {
    const database = yield* Prisma.ConnectionBinding(connection);

    return {
      fetch: Effect.gen(function* () {
        const databaseUrl = yield* database.databaseUrl;

        return HttpServerResponse.text(
          databaseUrl ? "database ready" : "database unavailable",
        );
      }),
    };
  }).pipe(Effect.provide(Prisma.ConnectionBindingLive)),
);

Local development and migrations

Database resources can configure @prisma/dev for local development. Production migrations can use the direct database URL while the deployed application receives the pooled URL:

const migrationUrl = Prisma.connectionUrl(connection, "direct");

const runtimeEnv = Prisma.connectionEnv(connection, {
  directUrl: false,
  pooledDatabaseUrl: false,
  connectionId: false,
  databaseId: false,
});

The checked-in TanStack Start example includes transactional Prisma Next migrations, excludes production seed data, and keeps migration credentials separate from runtime credentials.

Production deployment lifecycle

A Compute update follows a fail-closed deployment sequence:

  1. Build and archive the application.
  2. Upload the deployment artifact with bounded, streamed I/O.
  3. Start the candidate deployment.
  4. Verify its public preview health endpoint.
  5. Promote the candidate deployment.
  6. Confirm that the application reports the new deployment as latest.
  7. Verify the stable application endpoint.
  8. Only then stop or destroy the previous deployment.

Failed or ambiguous operations preserve the last healthy deployment. Terminally failed deployments are never restarted or selected as rollback targets. A previous deployment is removed only after the replacement is fully promoted and healthy.

Additional hardening includes:

  • Observed-state reconciliation and explicit adoption behavior
  • Idempotent create, update, replacement, and delete paths
  • Bounded retries, polling, and subprocess timeouts
  • Process-group termination for timed-out build commands
  • Streamed and file-backed uploads with explicit size limits
  • Path traversal, symlink, and build-artifact mutation checks
  • Redaction of connection strings and service tokens from state, logs, errors, artifacts, and subprocess output
  • Removal of ambient Prisma Management API credentials from build and migration subprocesses

Management API compatibility

The implementation is synchronized with the current prisma/pdp-control-plane Management API:

  • Uses the canonical /v1/apps and /v1/deployments routes
  • Does not rely on deprecated compute-service/version aliases
  • Covers all 71 canonical provider routes and operations used by the resource surface
  • Preserves endpoint-specific response semantics, including custom-domain 200 versus 201 behavior
  • Uses Management API state as the source of truth during reconciliation

Examples

Verification

  • bun tsc -b
  • Package build
  • Prisma provider tests: 349 passed, 3 credential-gated tests skipped
  • Command/process tests: 33 passed
  • Planning tests: 100 passed
  • Provider lint and formatting checks
  • Both example production builds
  • Documentation generation: 768 pages, with no broken links
  • Live deployment of both examples against Prisma
  • Public application and health endpoints returned 200
  • Database-backed configuration checks succeeded
  • Repeat deploys converged to exactly one active deployment
  • The Effect example reused the same healthy deployment on a no-op deploy
  • Both live stacks were destroyed and all verified resource endpoints returned 404

@AmanVarshney01 AmanVarshney01 changed the title Experimental Prisma provider cleanup Experimental Prisma provider for Alchemy May 22, 2026
@AmanVarshney01 AmanVarshney01 force-pushed the aman/prisma-alchemy-provider branch 3 times, most recently from 86a9960 to f2087fb Compare May 22, 2026 11:45
Comment thread packages/alchemy/src/Prisma/ComputeApp.ts Outdated
@sam-goodwin

Copy link
Copy Markdown
Contributor

Are you planning on adding an effect-native ComputeApp Platform and Bindings? One that works like Cloudflare Workers or Lambda Function?

https://v2.alchemy.run/concepts/platform/

@AmanVarshney01 AmanVarshney01 force-pushed the aman/prisma-alchemy-provider branch from f2087fb to c3af6c7 Compare May 26, 2026 06:50
@AmanVarshney01

Copy link
Copy Markdown
Author

Are you planning on adding an effect-native ComputeApp Platform and Bindings? One that works like Cloudflare Workers or Lambda Function?

https://v2.alchemy.run/concepts/platform/

Interesting didn’t know about this. I’ll get back to you on this in a bit.

@AmanVarshney01 AmanVarshney01 force-pushed the aman/prisma-alchemy-provider branch from c3af6c7 to 0952b7a Compare May 26, 2026 06:56
Comment thread examples/prisma-compute-effect/alchemy.run.ts Outdated
Comment thread examples/prisma-compute-effect/alchemy.run.ts Outdated
Comment thread examples/prisma-compute-effect/alchemy.run.ts Outdated
Comment thread examples/prisma-compute-effect/src/Api.ts Outdated
@AmanVarshney01 AmanVarshney01 changed the title Experimental Prisma provider for Alchemy feat: prisma provider Jun 16, 2026
@AmanVarshney01 AmanVarshney01 marked this pull request as ready for review June 16, 2026 12:25
AmanVarshney01 and others added 6 commits June 23, 2026 04:05
…rovider

# Conflicts:
#	.oxfmtrc.json
#	bun.lock
#	packages/alchemy/package.json
…PI surface

- rework ConnectionBinding to the single binding convention (alchemy-run#690): combined
  tag/callable + Binding.Host dispatch inside ConnectionBindingLive, drop
  Binding.Policy machinery and its Providers registrations
- replace the removed Build/Command helper (alchemy-run#673) with a local spawner-based
  runBuildCommand in ComputeBuild
- update shape-typed class forms to the id-only + .make(props, impl) Platform API
- add the /v1/apps, /v1/deployments, and build-logs surface to the client,
  operation helpers, and route-parity tests (96-route coverage)
- add ScmInstallation.connected/connectedAt, the connected list filter, and
  connectScmInstallation for the new SCM connect endpoint; unreleased routes
  are allowlisted until they ship to the production OpenAPI doc
@AmanVarshney01 AmanVarshney01 changed the title feat: prisma provider feat(prisma): add production management api provider Jul 10, 2026
@AmanVarshney01 AmanVarshney01 changed the title feat(prisma): add production management api provider feat: add Prisma provider Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants