What is Alchemy
Alchemy is an embeddable Infrastructure-as-Code (IaC) library written in pure TypeScript that runs anywhere that JavaScript runs - including the browser, serverless functions or even durable workflows.
What is Infrastructure as Code?
Section titled “What is Infrastructure as Code?”Infrastructure-as-Code is the practice of using code to define your infrastructure configuration instead of manually creating it.
Let’s say you need a database. Instead of clicking through a cloud console or executing a CLI command, you simply write:
const database = await Database("main", { engine: "postgres", size: "small",});
// Access properties directlyconsole.log(database.connectionString);
Run this code, and the actual database gets created. Run it twice without changes, and nothing happens. Change the size to "medium"
and run it again - your database will be updated. Remove the code and run it again, the database will be deleted.
Your code is the blueprint for repeatable infrastructure. Alchemy keeps track of all the resources and handles the synchronization between your code and the real world.
How is Alchemy different than traditonal IaC?
Section titled “How is Alchemy different than traditonal IaC?”Unlike similar tools like Terraform, Pulumi, SST and CloudFormation, Alchemy is implemented in pure ESM-native TypeScript code.
The Terraform, Pulumi and SST ecosystem are all tied together. SST is on top of Pulumi, which is again on top of Terraform. Terraform and Pulumi are implemented in Go and generate TypeScript “wrappers” that depend on a separate Go process.
The AWS CDK genereates CloudFormation JSON, depends on a managed service to run and only supports AWS services. Extending CloudFormation requires you deploy a Lambda Function (which is an ordeal).
All together, IaC without Alchemy is a clunky, heavy, opinionated toolchain that mostly works against you as a user. Alchemy simplifies the entire stack down to pure async functions.
Zero Dependencies
Section titled “Zero Dependencies”Alchemy adopts a philosophy of zero-dependencies and web standards so that it can run anywhere with minimal impact on bundle size.
All you gotta do is install alchemy
and you’re good to go.
bun add alchemy
Just Async Functions
Section titled “Just Async Functions”Resources in Alchemy are implemented with async functions instead of complex class abstractions with sharp edge gotchas, inter-process-communication or hosted services.
This means you can create resources in any async environment and gain access to its physical properties immediately:
// Create a resource by awaiting a functionconst worker = await Worker("api", { name: "my-api", entrypoint: "./src/index.ts",});
console.log(worker.workerName); // string
Contrast this with Pulumi which relies on a complex graph abstraction:
const worker = new Worker("api", { name: "my-api", entrypoint: "./src/index.ts",});
worker.workerName; // Output<string>
// requires a complex abstraction just to log a value 😵💫pulumi.export(worker.workerName);
Runs Anywhere
Section titled “Runs Anywhere”Alchemy works in any JavaScript environment including browsers, serverless functions, and durable workflows.
// Browser environmentconst app = await alchemy("my-browser-app");
// Lambda functionexport const handler = async () => { await alchemy.run("customer-id", async () => { await Worker(..) })};
Transparent State
Section titled “Transparent State”State is stored as plain JSON files you can inspect, edit, and version control.
{ "provider": "cloudflare::Worker", "status": "created", "output": { "id": "my-api", "url": "https://my-api.workers.dev" }, "props": { "name": "my-api", "entrypoint": "./src/index.ts" }}
Pluggable State
Section titled “Pluggable State”Alchemy supports custom state backends including file systems, cloud storage, or databases.
// Use Cloudflare R2 for stateimport { R2RestStateStore } from "alchemy/cloudflare";
const app = await alchemy("my-app", { stateStore: (scope) => new R2RestStateStore(scope, { bucketName: "my-state-bucket", }),});
By default, Alchemy assumes you want to store state files locally for development purposes, but since Alchemy can run anywhere - you may want to store state in the the browser, or a Cloudflare Durable Object!
Learn more about custom state stores
Direct API Integration
Section titled “Direct API Integration”
fetch
is all you need
Alchemy resources call service APIs directly using fetch
, instead of using SDKs that often come with heavy dependencies and runtime requirements.
// Resource implementation using direct API callsif (this.phase === "delete") { await fetch(`https://api.example.com/resources/${this.output.id}`, { method: "DELETE", headers: { Authorization: `Bearer ${apiKey}` }, }); return this.destroy();}
Custom Resources in Minutes
Section titled “Custom Resources in Minutes”Create new resource types with a simple function that implements create, update, and delete operations.
export const Database = Resource( "myservice::Database", async function ( this: Context<Database>, id: string, props: DatabaseProps ): Promise<Database> { if (this.phase === "delete") { // Delete logic return this.destroy(); } else if (this.phase === "update") { // Update logic return this({ id: "db-123", ...props }); } else { // Create logic return this({ id: "db-123", ...props }); } });
Optimized for AI
Section titled “Optimized for AI”Alchemy provides a .cursorrules
file to help AI tools generate resource implementations at 90% accuracy on the first try.
// 1. Copy Alchemy's .cursorrules into your repo// 2. Ask AI: "Create a resource for Neon Database"// 3. Get a working implementation in seconds
// Result: Complete implementation with proper lifecycle handlingexport const Database = Resource( "neon::Database", async function ( this: Context<Database>, id: string, props: DatabaseProps ): Promise<Database> { // Full resource implementation generated by AI });
Learn more about AI-generated resources
Fast Deployments
Section titled “Fast Deployments”Alchemy deployments are fast because they run directly in JavaScript without spawning external processes or slow toolchains.
// No IPC, no Go toolchains, no CloudFormation waiting// Just direct JavaScript execution calling APIs// $ time bun ./alchemy.run.ts// real 0m1.234s
Flexible Scoping
Section titled “Flexible Scoping”Alchemy organizes resources with a hierarchical scope system that supports infinite nesting and isolation.
// Root and stage scopesconst app = await alchemy("my-app", { stage: "prod", password: "prod-secret", // Encryption password for this scope});
Secure Secrets
Section titled “Secure Secrets”Alchemy encrypts sensitive values in state files.
// Define a secretconst apiKey = alchemy.secret(process.env.API_KEY);
// Use it in a resourceconst worker = await Worker("api", { bindings: { API_KEY: apiKey },});
// In state files, it's encrypted// "API_KEY": { "@secret": "Tgz3e/WAscu4U1oanm5S4YXH..." }
Scoped Encryption and State
Section titled “Scoped Encryption and State”Each scope can have a different encryption password and state store.
// Nested scopes can have different passwords and state storesawait alchemy.run( "backend", { password: "backend-secret", stateStore: new DatabaseStateStore(), }, async (scope) => { // Create resources in this scope await Worker("api", { /* ... */ });
// Deeper nesting works too await alchemy.run("database", async () => { await Database("main", { /* ... */ }); }); });
Application Examples
Section titled “Application Examples”Alchemy works for a wide range of infrastructure use cases.
// Cloudflare Workers and Static Sitesconst assets = await Assets("Assets", { path: "./dist",});
const site = await Worker("Website", { name: "my-app", bindings: { ASSETS: assets, },});
// AWS Lambda Functionsconst func = await Function("api", { handler: "src/lambda.handler", environment: { TABLE_NAME: table.name },});
// Third-party APIs like Stripeconst product = await Product("pro-plan", { name: "Pro Plan", description: "Professional subscription tier",});
Getting Started
Section titled “Getting Started”Ready to try Alchemy? Check out our Getting Started guide to build your first Alchemy app.