GCP.Run reference
bindPort
Section titled “bindPort”Source:
packages/gcp/src/Run/BindContainer.ts
Run a Container as a sidecar and reach one of its ports
directly — for a protocol other than HTTP, such as Redis or Postgres.
See bindContainer.
bindPort: Binding a port
Section titled “bindPort: Binding a port”export const Cache = GCP.Run.Container("Cache", { image: "docker.io/library/redis:7", port: 6379, startupProbe: { tcpSocket: {} },});
// inside the service's Effectconst cache = yield* GCP.Run.bindPort(Cache, 6379);// cache.url === "http://localhost:6379"; connect with `redis://localhost:${cache.port}`Container
Section titled “Container”Source:
packages/gcp/src/Run/Container.ts
A container that runs next to a Cloud Run service’s main container, in
the same instance. Bind it from the service with
bindContainer (typed RPC and fetch) or bindPort (a raw
port): binding adds it to the service’s revision and holds the service
back until the container passes its startup probe.
Give it main and an Effect implementation to run your own program —
Alchemy bundles it into its own image — or just an image.
Container: Declaring a Container
Section titled “Container: Declaring a Container”An Effect-native container with RPC methods
export default class Worker extends GCP.Run.Container<Worker>()( "Worker", { main: import.meta.url, port: 3000, startupProbe: { httpGet: { path: "/health" } }, }, Effect.gen(function* () { return { greet: (name: string) => Effect.succeed(`hello ${name}`), fetch: Effect.succeed(HttpServerResponse.text("ok")), }; }),) {}An image
export const Cache = GCP.Run.Container("Cache", { image: "docker.io/library/redis:7", port: 6379, startupProbe: { tcpSocket: {} },});Container: Using bindings
Section titled “Container: Using bindings”export default class Worker extends GCP.Run.Container<Worker>()( "Worker", { main: import.meta.url, port: 3000 }, Effect.gen(function* () { const publish = yield* GCP.PubSub.Publish(Tweets); return { post: (text: string) => publish({ body: { messages: [{ data: btoa(text) }] } }), }; }).pipe(Effect.provide(GCP.PubSub.PublishHttp)),) {}The binding’s env lands on this container. Its IAM roles go to the service account of the revision the container joins.
EffectApis
Section titled “EffectApis”Source:
packages/gcp/src/Run/EffectApis.ts
Serve an Effect RPC group as a Cloud Run service’s or container’s
fetch. Uses NDJSON, the serialization the schema clients of
bindContainer and InvokeService speak, so value and
streaming procedures both work.
EffectApis: Serving Effect RPC
Section titled “EffectApis: Serving Effect RPC”export default class Tasks extends GCP.Run.Container<Tasks>()( "Tasks", { main: import.meta.url, port: 3000 }, Effect.gen(function* () { return { fetch: GCP.Run.ServeRpc(TaskRpcs, TaskRpcs.toLayer({ getTask: ({ id }) => Effect.succeed(new Task({ id, title: "write docs" })), })), }; }),) {}EventarcEventSource
Section titled “EventarcEventSource”Source:
packages/gcp/src/Run/EventarcEventSource.tsKind: Layer · Provides:GCP.Eventarc.EventSource
HTTP implementation of GCP.Eventarc.EventSource for GCP.Run.Service
/ GCP.Function and GCP.CloudFunctions.Function.
Deploy-time: grants the host’s runtime service account
roles/eventarc.eventReceiver on the project and roles/run.invoker on
the host (and, for Cloud Storage events, the Storage service agent
roles/pubsub.publisher on the project, which direct Storage events
require), then creates the trigger with that account as its identity.
Each grant and the trigger block until GCP reports them in place and
healthy. Runtime: claims deliveries on the path, verifies the OIDC
token, decodes the binary-mode CloudEvent, and runs the handler; a 2xx
acks, a failed handler answers 500 and Eventarc redelivers.
GetService
Section titled “GetService”Source:
packages/gcp/src/Run/GetService.ts
Runtime binding for Cloud Run services.get.
Bind this operation to a Service in a Function/Action init phase.
Provide GetServiceHttp.
GetService: Reading a Service
Section titled “GetService: Reading a Service”const getService = yield* GCP.Run.GetService(api);const live = yield* getService();GetServiceHttp
Section titled “GetServiceHttp”Source:
packages/gcp/src/Run/GetServiceHttp.tsKind: Layer · Provides:GCP.Run.GetService
HTTP implementation of GetService.
GetWorkerPool
Section titled “GetWorkerPool”Source:
packages/gcp/src/Run/GetWorkerPool.ts
Runtime binding for Cloud Run workerPools.get.
Bind this operation to a WorkerPool in a Function/Action init
phase. Provide GetWorkerPoolHttp.
GetWorkerPool: Reading a Worker Pool
Section titled “GetWorkerPool: Reading a Worker Pool”const getWorkerPool = yield* GCP.Run.GetWorkerPool(pool);const live = yield* getWorkerPool();GetWorkerPoolHttp
Section titled “GetWorkerPoolHttp”Source:
packages/gcp/src/Run/GetWorkerPoolHttp.tsKind: Layer · Provides:GCP.Run.GetWorkerPool
HTTP implementation of GetWorkerPool.
InvokeServiceHttp
Section titled “InvokeServiceHttp”Source:
packages/gcp/src/Run/InvokeServiceHttp.tsKind: Layer · Provides:GCP.Run.InvokeService
HTTP implementation of InvokeService: ID tokens from the Cloud
Run metadata server, requests over the ambient HttpClient.
Source:
packages/gcp/src/Run/Job.ts
A Cloud Run Job — a container that runs to completion.
Changing jobId or location replaces the job.
Job: Creating a Job
Section titled “Job: Creating a Job”Generated name
const job = yield* GCP.Run.Job("Migrate", { containers: [ { image: "us-docker.pkg.dev/cloudrun/container/job:latest" }, ],});Explicit id, labels, and retries
const job = yield* GCP.Run.Job("Migrate", { jobId: "order-migrate", location: "us-central1", labels: { env: "prod" }, maxRetries: 1, timeout: "120s", containers: [ { image: "us-docker.pkg.dev/cloudrun/container/job:latest", env: [{ name: "STAGE", value: "prod" }], }, ],});Job: Effect-native Job with bindings
Section titled “Job: Effect-native Job with bindings”export class Warm extends GCP.Run.Job<Warm>()( "Warm", { main: import.meta.url }, Effect.gen(function* () { const redis = yield* GCP.Redis.ReadWriteRedis(cache); return { run: redis.set("warmed", "1"), }; }).pipe(Effect.provide(GCP.Redis.ReadWriteRedisHttp)),) {}Job: Caching Build Layers
Section titled “Job: Caching Build Layers”Builds reuse the local BuildKit cache of the machine they run on, and
nothing but the image is pushed. A builder that has never built the image,
such as a fresh CI runner, reruns every step. Set build.cache: true to keep
every stage’s layers at the image repository’s :buildcache tag, so fresh
builders skip unchanged steps. For another backend, pass BuildKit’s own
--cache-from / --cache-to values as from and to.
Cache layers in Artifact Registry
const migrate = yield* GCP.Run.Job("Migrate", { main: import.meta.url, build: { cache: true },});Cache layers in GitHub Actions
const migrate = yield* GCP.Run.Job("Migrate", { main: import.meta.url, build: { cache: { from: ["type=gha,scope=migrate"], to: ["type=gha,scope=migrate,mode=max"], }, },});Job: Running a Job
Section titled “Job: Running a Job”const runJob = yield* GCP.Run.RunJob(job);yield* runJob();RunJob
Section titled “RunJob”Source:
packages/gcp/src/Run/RunJob.ts
Runtime binding for Cloud Run jobs.run.
Triggers a new execution of the bound Job. Provide
RunJobHttp.
RunJob: Running Jobs
Section titled “RunJob: Running Jobs”Trigger an execution
const runJob = yield* GCP.Run.RunJob(job);yield* runJob();Override task count
const runJob = yield* GCP.Run.RunJob(job);yield* runJob({ body: { overrides: { taskCount: 1 } },});RunJobHttp
Section titled “RunJobHttp”Source:
packages/gcp/src/Run/RunJobHttp.tsKind: Layer · Provides:GCP.Run.RunJob
HTTP implementation of RunJob.
ScheduleEventSource
Section titled “ScheduleEventSource”Source:
packages/gcp/src/Run/ScheduleEventSource.tsKind: Layer · Provides:GCP.CloudScheduler.ScheduleEventSource
Implementation of GCP.CloudScheduler.ScheduleEventSource for HTTP
hosts (GCP.Run.Service / GCP.Function, GCP.CloudFunctions.Function).
Deploy-time: grants the host’s runtime service account
roles/run.invoker on the host and creates a Cloud Scheduler job that
POSTs to the host’s URL with an OIDC token for that account. Runtime:
claims the job’s deliveries on its path, verifies the token, and runs
the handler with the X-CloudScheduler-* headers. 204 marks the run
successful; a failed handler answers 500 and the job’s retry policy
applies.
ScheduleEventSource: Running on a schedule
Section titled “ScheduleEventSource: Running on a schedule”Effect.gen(function* () { yield* GCP.CloudScheduler.consumeSchedule( "Sweep", { schedule: "every 5 minutes" }, (event) => Effect.log(`sweep ${event.scheduleTime}`), );}).pipe(Effect.provide(GCP.Run.ScheduleEventSource));Service
Section titled “Service”Source:
packages/gcp/src/Run/Service.ts
A Cloud Run service (Knative serving revision + traffic).
Changing serviceId or location replaces the service. Updates to
template create a new revision.
This is GCP’s effectful HTTP platform — the analog of
AWS.Lambda.Function / Cloudflare.Worker. Pass main plus an
Effect implementation; bindings grant IAM onto the runtime service
account and inject env, the way AWS policyStatements land on the
execution role.
Service: Creating a Service
Section titled “Service: Creating a Service”Generated name, default hello image
const api = yield* GCP.Run.Service("api", {});Explicit id, image, env, and labels
const api = yield* GCP.Run.Service("api", { serviceId: "order-api", location: "us-central1", description: "order HTTP API", labels: { env: "prod" }, ingress: "INGRESS_TRAFFIC_ALL", template: { timeout: "60s", containers: [ { image: "us-docker.pkg.dev/cloudrun/container/hello", env: [{ name: "ENV", value: "prod" }], }, ], },});Service: Health Probes and Sidecars
Section titled “Service: Health Probes and Sidecars”HTTP startup probe, with a proxy that starts after the app
const api = yield* GCP.Run.Service("api", { template: { containers: [ { name: "proxy", image: proxyImage, ports: [{ name: "h2c", containerPort: 8080 }], dependsOn: ["app"], }, { name: "app", image: appImage, startupProbe: { httpGet: { path: "/health", port: 3000 }, periodSeconds: 2, failureThreshold: 30, }, livenessProbe: { httpGet: { path: "/health", port: 3000 }, periodSeconds: 10 }, }, ], },});TCP and gRPC probes
startupProbe: { tcpSocket: { port: 5432 }, initialDelaySeconds: 5 },livenessProbe: { grpc: { port: 9090, service: "health" }, timeoutSeconds: 3 },Changing a probe or dependsOn rolls a new revision. Removing
startupProbe restores Cloud Run’s default TCP probe.
Effect-native service with a sidecar
export class Api extends GCP.Run.Service<Api>()( "Api", { main: import.meta.url, template: { containers: [ { // image, ports and env are filled in from `main` startupProbe: { httpGet: { path: "/health" } }, dependsOn: ["cache"], }, { name: "cache", image: "docker.io/library/redis:7", startupProbe: { tcpSocket: { port: 6379 } }, }, ], }, }, Effect.gen(function* () { return { fetch: Effect.gen(function* () { const request = yield* HttpServerRequest; if (request.url === "/health") return HttpServerResponse.text("ok"); return HttpServerResponse.text("hello"); }), }; }),) {}The first container runs main; the rest deploy as sidecars.
An image service with an Effect-native sidecar
const worker = yield* Worker; // a GCP.Run.Containerconst api = yield* GCP.Run.Service("api", { template: { containers: [ { image: proxyImage, ports: [{ containerPort: 8080 }], dependsOn: [worker.name] }, worker, ], },});A listed Container brings its bindings’ roles and the sidecars it binds.
worker.name is an Output that resolves to the container’s name in the
revision, so the proxy starts after it.
Service: Effect-native Function with bindings
Section titled “Service: Effect-native Function with bindings”const tweets = yield* GCP.PubSub.Topic("tweets", {});const cache = yield* GCP.Redis.Instance("Cache", { memorySizeGb: 1 });
export class TweetBot extends GCP.Run.Service<TweetBot>()( "TweetBot", { main: import.meta.url }, Effect.gen(function* () { const publish = yield* GCP.PubSub.Publish(tweets); const redis = yield* GCP.Redis.ReadWriteRedis(cache); return { fetch: Effect.gen(function* () { const text = (yield* redis.get("last-tweet")) ?? "hello twitter"; yield* publish({ body: { messages: [{ data: btoa(text) }] }, }); return HttpServerResponse.text("queued"); }), }; }).pipe( Effect.provide([ GCP.PubSub.PublishHttp, GCP.Redis.ReadWriteRedisHttp, ]), ),) {}Service: Calling AWS without keys
Section titled “Service: Calling AWS without keys”An AWS binding gives the service an IAM role that trusts its runtime
service account’s Google ID tokens. The service assumes the role with
AssumeRoleWithWebIdentity, so no AWS access key is created.
const jobs = yield* AWS.SQS.Queue("Jobs");
export class Api extends GCP.Run.Service<Api>()( "Api", { main: import.meta.url }, Effect.gen(function* () { const send = yield* AWS.SQS.SendMessage(jobs); return { fetch: send({ MessageBody: "hello" }).pipe( Effect.as(HttpServerResponse.text("sent")), ), }; }).pipe(Effect.provide(AWS.SQS.SendMessageHttp)),) {}Service: Caching Build Layers
Section titled “Service: Caching Build Layers”Builds reuse the local BuildKit cache of the machine they run on, and
nothing but the image is pushed. A builder that has never built the image,
such as a fresh CI runner, reruns every step. Set build.cache: true to keep
every stage’s layers at the image repository’s :buildcache tag, so fresh
builders skip unchanged steps. For another backend, pass BuildKit’s own
--cache-from / --cache-to values as from and to.
Cache layers in Artifact Registry
const api = yield* GCP.Run.Service("Api", { main: import.meta.url, build: { cache: true },});Cache layers in GitHub Actions
const api = yield* GCP.Run.Service("Api", { main: import.meta.url, build: { cache: { from: ["type=gha,scope=api"], to: ["type=gha,scope=api,mode=max"], }, },});Service: Updating a Service
Section titled “Service: Updating a Service”const api = yield* GCP.Run.Service("api", { template: { timeout: "120s", containers: [{ image: "us-docker.pkg.dev/cloudrun/container/hello" }], },});Template changes create a new revision. The runtime service account is kept.
Service: Destroying a Service
Section titled “Service: Destroying a Service”Service: Reading a Service
Section titled “Service: Reading a Service”const getService = yield* GCP.Run.GetService(api);const live = yield* getService();TopicEventSource
Section titled “TopicEventSource”Source:
packages/gcp/src/Run/TopicEventSource.tsKind: Layer · Provides:GCP.PubSub.TopicEventSource
Push implementation of GCP.PubSub.TopicEventSource for HTTP hosts
(GCP.Run.Service / GCP.Function, GCP.CloudFunctions.Function).
Deploy-time: grants the host’s runtime service account
roles/run.invoker on the host and creates a push subscription to the
host’s URL, signed with an OIDC token for that account. Runtime: claims
POST deliveries on the push path, verifies the token, and runs the
handler. 204 acks the message; a failed handler answers 500 and Pub/Sub
redelivers per the subscription’s retry policy.
TopicPullEventSource
Section titled “TopicPullEventSource”Source:
packages/gcp/src/Run/TopicPullEventSource.tsKind: Layer · Provides:GCP.PubSub.TopicEventSource
Pull implementation of GCP.PubSub.TopicEventSource for hosts without
an inbound URL (GCP.Run.Job, GCP.Run.WorkerPool; any host with
ServerHost).
Deploy-time: creates a pull subscription owned by the host and grants
the host’s runtime service account roles/pubsub.subscriber on it
(through the Pull / Acknowledge bindings). Runtime: a background
loop pulls batches, runs the handler, and acks the batch once the
handler succeeds. A failed handler leaves the batch unacked, so Pub/Sub
redelivers after the ack deadline.
WorkerPool
Section titled “WorkerPool”Source:
packages/gcp/src/Run/WorkerPool.ts
A Cloud Run worker pool (pull-based revision + instance split).
Changing workerPoolId or location replaces the pool. Updates to
template create a new revision.
WorkerPool: Creating a Worker Pool
Section titled “WorkerPool: Creating a Worker Pool”Generated name, default worker image
const pool = yield* GCP.Run.WorkerPool("workers", {});Explicit id, image, env, and labels
const pool = yield* GCP.Run.WorkerPool("workers", { workerPoolId: "order-workers", location: "us-central1", description: "order pull workers", labels: { env: "prod" }, scaling: { manualInstanceCount: 1 }, template: { containers: [ { image: "us-docker.pkg.dev/cloudrun/container/worker-pool", env: [{ name: "ENV", value: "prod" }], }, ], },});WorkerPool: Reading a Worker Pool
Section titled “WorkerPool: Reading a Worker Pool”const getWorkerPool = yield* GCP.Run.GetWorkerPool(pool);const live = yield* getWorkerPool();WorkerPool: Effect-native Worker Pool with bindings
Section titled “WorkerPool: Effect-native Worker Pool with bindings”export class Workers extends GCP.Run.WorkerPool<Workers>()( "Workers", { main: import.meta.url, scaling: { manualInstanceCount: 1 } }, Effect.gen(function* () { const redis = yield* GCP.Redis.ReadWriteRedis(cache); return { run: redis.set("worker", "up"), }; }).pipe(Effect.provide(GCP.Redis.ReadWriteRedisHttp)),) {}