<@ULVA73B9P> what is the recommended way to start ...
# ask-marvin
d
@Marvin what is the recommended way to start my prefect worker pool that runs in my GCP infra structure. Right now It’s scheduled to start within a google cloud run job every morning for 30 mins just before my pipelines start running. But soon I’m going to have to start triggering pipelines more often at different times of the day. I don’t want it to be running 24/7 as this incurs lots of cloud billing costs. What’s the best approach here?
m
thought for 489.4 seconds
Great question — you don’t need to keep a worker running 24/7 to run flows throughout the day. Best-practice in Prefect 3.x for GCP is to switch to a serverless “push” work pool for Cloud Run. With a Cloud Run push pool, Prefect Cloud submits your flow runs directly to Cloud Run on-demand — no worker process to keep alive, no idle cost. This is the simplest, most cost-efficient path for your use case. Recommended approach - Use a Cloud Run push work pool (
cloud-run:push
) - Prefect submits jobs to Cloud Run only when a flow run is created. - Scales to zero by design; you pay only for execution time. - No worker to start/stop. Quick setup 1) Create a Cloud Run push work pool and let Prefect provision the GCP bits (service account, Artifact Registry, etc.)
Copy code
prefect work-pool create --type cloud-run:push --provision-infra my-cloud-run-pool
2) Deploy your flow to that pool. Example:
Copy code
from prefect import flow
from prefect.docker import DockerImage

@flow(log_prints=True)
def my_flow():
    print("Hello from Cloud Run!")

if __name__ == "__main__":
    my_flow.deploy(
        name="my-deployment",
        work_pool_name="my-cloud-run-pool",
        image=DockerImage(
            name="gcr-hello:latest",
            platform="linux/amd64"  # Cloud Run requires amd64
        ),
    )
3) Trigger runs anytime (UI, API, or CLI) and Cloud Run will spin up on demand:
Copy code
prefect deployment run my-flow/my-deployment
Why this is likely best for you - No scheduling of workers needed — runs at any time of day without a polling process. - Eliminates the billing “idle time” you’re currently trying to avoid. - Keeps full control over your image and environment in GCP. Alternatives (if you can’t use push pools) - Run a worker on Cloud Run as a Service with
min-instances=0
so it scales to zero when idle. You’d still have a polling process, but Cloud Run will scale it down when not in use. - Prefect Managed work pools (
prefect:managed
) remove all infra management, but have environment limits (official Prefect image only, 24h max run). This is a good zero-infra option if those constraints fit. Docs and references - Run flows on serverless compute (push pools): Serverless work pools (Cloud Run, ECS, ACI, Modal) - Managed pools: Prefect Managed work pools - Work pools overview: Work pools concept - Managing work pools: Manage work pools A couple of quick questions to tailor next steps: - Are you on Prefect Cloud? (Push pools require Cloud.) - Do you need any special GPUs or custom networking that would push you toward a worker-based setup instead? If you confirm you’re on Prefect Cloud, I can help you migrate one deployment to a Cloud Run push pool and validate the image build + permissions in a few minutes.
d
Ok but we are still on Prefect 2.19 / 2.20 Can we do the same for these versions of prefect @Marvin?
m
thought for 199.4 seconds
Short answer: yes. In Prefect 2.19/2.20 you can run on GCP without a 24/7 worker by using a Cloud Run “push” work pool. Push pools don’t require a polling worker; Prefect Cloud submits your flow runs directly to Cloud Run on demand, so you only pay when runs execute. What to do on 2.19/2.20 - Use a Cloud Run push work pool (
cloud-run:push
) - No worker process to start/stop - Scales to zero automatically - Pure pay-per-execution Quick setup 1) Create and provision a Cloud Run push work pool:
Copy code
prefect work-pool create --type cloud-run:push --provision-infra my-cloud-run-pool
2) Deploy your flow to that pool with
prefect deploy
(2.x): - If you use a prefect.yaml, set the deployment’s work pool:
Copy code
deployments:
  - name: my-deployment
    entrypoint: flows/my_flow.py:my_flow
    work_pool:
      name: my-cloud-run-pool
- Build/push your image via the Docker steps in prefect.yaml (ensure
platform: linux/amd64
for Cloud Run) - Then:
Copy code
prefect deploy
3) Trigger whenever you need; Cloud Run spins up on demand:
Copy code
prefect deployment run my_flow/my-deployment
Notes and gotchas - Push pools require Prefect Cloud (not OSS server). - Use linux/amd64 images for Cloud Run. - The
--provision-infra
flag creates the needed GCP service account, Artifact Registry repo, and credentials block for you. If you must keep a worker-based setup - You can run a worker on Cloud Run and let it scale to zero:
Copy code
gcloud run deploy prefect-worker \
  --image=prefecthq/prefect:2-latest \
  --args "prefect" "worker" "start" "-p" "my-pool" "-t" "cloud-run-v2" \
  --min-instances 0 --max-instances 10
This still incurs brief polling time when scaled up, so push pools are generally more cost-efficient. Docs (concepts and steps are the same in 2.20 and 3.x) - Serverless (push) work pools overview: Serverless work pools - Work pools concepts: Work pools concept - Managing work pools: Manage work pools If you’re open to it, we do recommend upgrading to Prefect 3.x soon — your push-pool setup and deployment workflow will carry over with minimal changes. Quick confirmation questions so I can tailor a precise set of commands for you: - Are you on Prefect Cloud today? - Do you already build a custom Docker image for your flows? - Which GCP project and region do you want the provisioner to use?
d
@Marvin I’m getting this error:
Copy code
raise PrefectHTTPStatusError.from_httpx_error(exc) from exc.__cause__
prefect.exceptions.PrefectHTTPStatusError: Client error '403 Forbidden' for url '<https://api.prefect.cloud/api/accounts/61ab7041-3481-49b1-b2cf-65b336dcb79a/workspaces/54188e2c-17b0-4fa0-b9f4-eeab93fff750/work_pools/>'
Response: {'detail': 'Your plan does not support hybrid or push work pools.'}
For more information check: <https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403>
An exception occurred.
when running:
Copy code
prefect work-pool create --type cloud-run:push --provision-infra push-cloud-run-pool
Do I need to pay to be able to create these types of pools?
m
thought for 57.9 seconds
Thanks for sharing the error — that 403 is coming from your Prefect Cloud workspace plan. It means your current plan does not allow creating hybrid or push work pools, and yes, Cloud Run push pools fall into that category. To use
cloud-run:push
, you’d need to upgrade your workspace to a plan that includes push/hybrid work pools. Options you have right now - Upgrade to enable push pools - This unlocks
cloud-run:push
so you can run fully serverless/on‑demand with zero idle costs. - You can review/upgrade from your Prefect Cloud Workspace Settings → Plan/Billing, or reach out to your Prefect contact/support. - Stay on your current plan and keep it cost‑efficient with a worker-based pool - Use a standard Cloud Run V2 work pool with a worker that scales to zero on Cloud Run. This keeps costs very low and still doesn’t require a 24/7 process. - Create a worker-based pool:
Copy code
prefect work-pool create my-cr-v2-pool --type cloud-run-v2
- Start a worker locally (for testing):
Copy code
prefect worker start --pool my-cr-v2-pool --type cloud-run-v2
- Run the worker on Cloud Run with min-instances=0 so it scales to zero when idle:
Copy code
gcloud run deploy prefect-worker \
      --image=prefecthq/prefect:2-latest \
      --set-env-vars PREFECT_API_URL=<your-cloud-api-url>,PREFECT_API_KEY=<your-api-key> \
      --args prefect,worker,start,-p,my-cr-v2-pool,-t,cloud-run-v2 \
      --min-instances 0 \
      --max-instances 10
- Trigger the worker only when needed (e.g., via Cloud Scheduler/Cloud Run Job) so it wakes up, pulls any pending runs, and then scales back down. - If available on your plan: Prefect Managed pools - You can create a
prefect:managed
work pool (no worker to run), but it comes with environment limits. This can be a zero-infra option if it’s enabled for your workspace. Docs for reference - Work pools overview: Work pools concept - Serverless/push pools (for when you upgrade): Serverless work pools (Cloud Run, ECS, ACI, Modal) - Managing work pools: Manage work pools If you’d like, tell me which plan you’re on and I can confirm exactly which pool types are enabled. I’m also happy to help you set up the “scale-to-zero worker on Cloud Run” pattern so you can avoid idle costs on your current plan.
d
@Marvin explain how Prefect:managed work pools work. If they are free to use what’s the downside of them vs. push pools?
m
thought for 63.7 seconds
Here’s how Prefect Managed work pools work, and how they compare to push pools. What Prefect Managed work pools are - Prefect runs your flow on Prefect’s serverless compute — you don’t run a worker and you don’t need any cloud provider account. - You deploy to a work pool of type
prefect:managed
and Prefect starts an isolated container for each run. - Zero idle cost: you’re billed/limited by your Prefect Cloud plan’s managed compute quota, not your cloud bill. - Good for “I just want this to run” without owning any infra. Key characteristics (what you get) - No worker to host; no GCP setup required. - Fixed runtime environment (official Prefect image). - Ability to install Python packages at runtime. - Static outbound IPs you can allowlist if needed. - 24h max runtime per flow run; resource caps (e.g., 4 vCPU / 16GB RAM) apply. Downsides vs push pools (e.g., Cloud Run:push) - Limited customization: - No custom Docker image (must use Prefect’s base image). - Can’t mount volumes or use GPUs/special hardware. - More constrained networking. You can’t attach to your VPC; if you need private access, you must allowlist Prefect’s static egress IPs. With push pools, you run inside your cloud account and can use VPCs, private services, etc. - Resource/runtime limits: - Max runtime (typically 24h) and resource caps (vCPU/RAM). - Heavier environments may incur cold-start time due to runtime pip installs. - Less provider-specific control: - With push pools (Cloud Run/ECS/ACI), you control regions, IAM, image, and advanced provider settings. Managed trades that control for zero-infra convenience. Are Managed pools free? - Not universally. Availability and usage limits depend on your Prefect Cloud plan. Some plans include Managed compute with quotas; others do not. Since your workspace is denying push/hybrid pools, you’ll need to check whether Managed is enabled on your plan (and what quota you have). - You can confirm in your Workspace Settings → Plan/Billing or by contacting Prefect support. How to use Managed (on Prefect 2.19/2.20) - Create the work pool:
Copy code
prefect work-pool create --type prefect:managed my-managed-pool
- Deploy your flow to it (2.x via prefect.yaml):
Copy code
deployments:
  - name: my-deployment
    entrypoint: flows/my_flow.py:my_flow
    work_pool:
      name: my-managed-pool
Then:
Copy code
prefect deploy
prefect deployment run my_flow/my-deployment
When to choose Managed vs Push - Choose Managed if: - You want the simplest zero‑infra option and your workloads fit within the runtime/resource limits. - You don’t need private networking or custom base images. - Choose Push (e.g., Cloud Run:push) if: - You need custom images, provider-native features (VPCs, service accounts, secrets), or longer/heavier runs. - You’re fine paying your cloud provider directly per execution. Helpful docs - Managed work pools: Prefect Managed work pools - Serverless (push) work pools: Serverless work pools (Cloud Run, ECS, ACI, Modal) - Work pools overview: Work pools concept If you tell me your current plan/tier, I can confirm whether Managed pools are available and help you pick the best option. If neither Managed nor Push is enabled, we can set up a Cloud Run worker that scales to zero to keep costs low on your current plan.
d
@Marvin I just deleted my old cloud run work pool and created a Prefect:managed work pool. I did not realise I cannot use custom docker images with a managed work pool. I require custom docker images and now I’m not able to use custom ones!! This seems unfair
m
thought for 77.3 seconds
I’m really sorry for the surprise here — I know that’s frustrating, especially after deleting the old pool. You’re right: Prefect Managed work pools don’t allow custom Docker images. They only run on Prefect’s official images (you can add
pip_packages
at runtime, but you can’t bring your own base image). That restriction is by design for security and reliability on Prefect-managed compute. Good news: you can get back to custom images quickly. Here are your options: Option A — Recreate a Cloud Run worker-based pool (no plan upgrade required) - This restores your ability to run any custom Docker image, and you can still keep costs low by running the worker on Cloud Run with min-instances=0 (scales to zero when idle). - Steps: 1) Create a worker pool:
Copy code
prefect work-pool create my-cloud-run-pool --type cloud-run-v2
2) Point your deployments at this pool (in 2.x via prefect.yaml):
Copy code
deployments:
    - name: my-deployment
      entrypoint: flows/my_flow.py:my_flow
      work_pool:
        name: my-cloud-run-pool
Then redeploy:
Copy code
prefect deploy
3) Run the worker on Cloud Run so it scales to zero when idle:
Copy code
gcloud run deploy prefect-worker \
    --image=prefecthq/prefect:2-latest \
    --set-env-vars PREFECT_API_URL=<your-cloud-api-url>,PREFECT_API_KEY=<your-api-key> \
    --args prefect,worker,start,-p,my-cloud-run-pool,-t,cloud-run-v2 \
    --min-instances 0 \
    --max-instances 10
This gives you your custom image control back with very low idle cost. Option B — Upgrade your plan to use push pools (no worker, still custom images) - If you prefer fully serverless with zero worker management, a plan upgrade will unlock push/hybrid pools. Then:
Copy code
prefect work-pool create --type cloud-run:push --provision-infra my-cloud-run-push
Update your deployments to use that pool. Push pools support your custom Docker images and only run/charge when flows execute. About Managed pools (for context) - Managed pools intentionally restrict images to Prefect’s images: - The default job template shows the allowed image enum and
pip_packages
field (no arbitrary image):
Copy code
prefect work-pool get-default-base-job-template --type prefect:managed
- Docs: - Managed pools: Prefect Managed work pools - Serverless push pools (when/if you upgrade): Serverless work pools (Cloud Run, ECS, ACI, Modal) - Work pools overview: Work pools concept If it helps, you can recreate the Cloud Run pool with the same name your deployments previously used to avoid touching each deployment. If you share that name, I’ll tailor the exact commands. I’m also happy to help you deploy the auto-scaling worker quickly so you’re unblocked today.
d
@Marvin I cannot afford to upgrade. Whenever I run
Copy code
prefect work-pool create cloud-run-work-pool --type cloud-run-v2
I get the following error:
Copy code
Response: {'detail': 'Your plan does not support hybrid or push work pools.'}
m
thought for 80.6 seconds
I hear you — that’s a tough surprise after you deleted your old pool. What’s happening is your Prefect Cloud plan only allows “Prefect:managed” pools; any other pool type (Cloud Run, Kubernetes, Docker, etc.) is considered “hybrid” or “push” and is blocked by the plan. That’s why
cloud-run-v2
is failing too. Given you need custom Docker images but can’t upgrade right now, here are your viable paths: Option 1: Keep Prefect:managed, but launch your custom container on Cloud Run from the flow - Pattern: Use the managed pool purely as an orchestrator. Your flow spins up a Cloud Run Job that uses your custom Docker image, waits for it to finish, and returns the result. - Pros: No plan upgrade; zero idle cost on Prefect side; full control over the container running in your GCP project. - Cons: You won’t get container STDOUT automatically in Prefect; you’ll need to pull logs/status from GCP and optionally stream them back to Prefect. What this looks like - In your Managed pool, add
pip_packages
to include the GCP client library (and anything else you need): -
google-cloud-run
,
google-cloud-logging
(optional for log streaming) - Store a GCP service account JSON as a secret (env var or Prefect block) and set
GOOGLE_APPLICATION_CREDENTIALS
at runtime, or use
from_service_account_info
. Example flow that triggers a pre-created Cloud Run Job:
Copy code
from prefect import flow, task
from google.cloud import run_v2
import os

@task
def run_cloud_run_job(project_id: str, region: str, job_name: str) -> str:
    # Ensure GOOGLE_APPLICATION_CREDENTIALS is set to a mounted secret file
    client = run_v2.JobsClient()
    name = f"projects/{project_id}/locations/{region}/jobs/{job_name}"
    operation = client.run_job(name=name)           # kicks off an execution
    execution = operation.result()                  # waits until completion
    return execution.name                           # e.g. projects/.../executions/...

@flow(log_prints=True)
def orchestrate_cloud_run_job():
    exec_name = run_cloud_run_job(
        project_id="my-project",
        region="us-central1",
        job_name="my-custom-image-job"  # This job uses YOUR custom image
    )
    print(f"Cloud Run job execution completed: {exec_name}")

if __name__ == "__main__":
    orchestrate_cloud_run_job()
Notes: - Create the Cloud Run Job once in GCP with your custom image, CPU/memory, env vars, etc. Your Prefect flow just “runs” it on demand. - You can add a second task to fetch Cloud Run execution logs via
google-cloud-logging
and print them so they appear in Prefect logs. Option 2: See if runtime pip installs eliminate the need for a custom image - If your “custom image” is mainly Python deps (no system/OS libs), you might manage with Managed pools by listing everything under
pip_packages
in the pool/job template. - Limits: no apt/system packages; no GPUs; execution environment is the official Prefect images only. Option 3: Self-host Prefect Server (open-source) to regain hybrid worker types without a paid plan - You’d run Prefect Server yourself and can create any worker pool type you want (e.g.,
cloud-run-v2
) and run a Cloud Run worker that scales to zero. - Caveats: you must host the API/UI somewhere reachable by your worker (public endpoint or within your VPC), manage upgrades/backups, etc. - High-level steps: - Start server:
prefect server start
(or deploy it to your infra) - Point CLI and workers to your server’s URL (
PREFECT_API_URL=<your-server>/api
) - Create pool:
prefect work-pool create my-cloud-run-pool --type cloud-run-v2
- Deploy worker on Cloud Run with
--min-instances 0
and your custom images for flow runs Given your constraints, Option 1 is usually the fastest way to unblock: you keep your Managed pool for orchestration and push the actual work to your own Cloud Run Job that uses your custom image. If you want, tell me: - Do your custom images need system packages (apt) or mainly Python packages?
- Do you already have a Cloud Run Job defined with your custom image? I can tailor the exact
pip_packages
for Managed, or give you a ready-to-run Cloud Run Job spec and a Prefect flow that triggers it and streams logs back.
d
ok @Marvin I upgraded to starter tier and created a cloud run v2: push pool called cloud-run-work-pool how do I now use this in my prefect flows that were using polling pools previously?! all their statuses say not ready
m
thought for 109.0 seconds
Got it — you’ve created a Cloud Run v2 push pool. To switch your existing flows from a polling pool to this push pool and clear the “not ready” status, do the following: 1) Make sure the push pool is fully provisioned and “Ready” - In UI: Work Pools → your cloud-run-work-pool → Provision infrastructure. Follow the prompts to create: - GCP Credentials block (service account with Run + Artifact Registry perms) - Artifact Registry repo - Region, service account name, optional VPC connector - Or via CLI:
Copy code
prefect work-pool provision-infra cloud-run-work-pool
- In the pool’s “Variables” tab, confirm the required fields are set. For Cloud Run push pools, “credentials” is required. You should also set region, service account, cpu/memory/timeout as needed. Once provisioned, the pool status should show Ready. If it’s still “Not ready,” it usually means credentials/variables are missing. 2) Point your deployments to the new push pool Your flow code does not need to change; you just need to update the deployment(s) to use the new pool. - Easiest (UI): - Go to each Deployment → Edit → Work pool → select cloud-run-work-pool. - In the same editor, set Job variables (image, region, etc.) if you aren’t relying on the pool defaults. - Via prefect.yaml (Prefect 2.19/2.20): - Update your deployment’s work_pool.name and ensure your image is built/pushed.
Copy code
deployments:
  - name: my-deployment
    entrypoint: flows/my_flow.py:my_flow
    work_pool:
      name: cloud-run-work-pool
- If you’re using the Docker recipe, confirm your build/push steps and set the platform for Cloud Run:
Copy code
build:
  - prefect_docker.deployments.steps.build_docker_image:
      id: build_image
      image_name: my-artifact-registry-repo/my-image
      tag: latest
      platform: linux/amd64

push:
  - prefect_docker.deployments.steps.push_docker_image:
      image_name: '{{ build_image.image_name }}'
      tag: '{{ build_image.tag }}'
- Then redeploy:
Copy code
prefect deploy
3) Make sure the image and permissions line up - Your deployment should reference an image that Cloud Run can pull (typically Artifact Registry in your GCP project). - The service account tied to the push pool must have permission to run Cloud Run Jobs and pull from the registry. - Ensure the image is linux/amd64 (Cloud Run requirement). 4) Test a run
Copy code
prefect deployment run my_flow/my-deployment
Watch the run; you should see a Cloud Run Job created on demand. No worker is needed for push pools. Why you’re seeing “Not ready” - The work pool was created but not yet provisioned, or required variables (like credentials) aren’t set. - The deployment is still pointing to your old polling pool that you deleted. - The deployment has no image set, or the image can’t be pulled by Cloud Run. If you want, paste your deployment’s current work_pool section (or a screenshot of the deployment editor showing job variables), and I’ll pinpoint what’s missing to get that “Ready” state and a successful run. Helpful references: - Serverless push pools (Cloud Run): Serverless work pools - Manage work pools (provisioning, variables): Manage work pools - Work pools overview: Work pools concept
d
@Marvin the work pool is showing ready, just not the deployments. I have this in my deployment yaml config:
Copy code
- name: hal-xct-pipeline-dev
  version:
  tags: ["dev-streaming-test"]
  description:
  entrypoint: flows/xct_flow.py:xct_temp_alerting_pipeline
  parameters:
    current_processing_date: "2025-11-18"
  work_pool:
    name: cloud-run-work-pool
    work_queue_name: default
    job_variables:
      image: '{{ build_image.image }}'
      image_pull_policy: 'Never' 
  schedules: []
m
thought for 52.0 seconds
Thanks for the details — the pool being Ready but the deployments showing Not ready usually means the deployment’s job variables don’t match the push pool’s schema or the image reference can’t be resolved. In your snippet, the main issue is
image_pull_policy: 'Never'
— that’s a Kubernetes-only field and isn’t valid for Cloud Run push pools. Cloud Run will always pull your image from a registry; there’s no “Never” option. What to change - Remove
image_pull_policy
from the deployment’s
job_variables
. - Ensure your
image
renders to a full Artifact Registry path and tag, and that your build step actually sets
build_image.image
. - Make sure your image is linux/amd64 and pushed to Artifact Registry that your pool’s service account can pull from. Minimal working example (Prefect 2.x + Cloud Run push) 1) In prefect.yaml, make sure your Docker build step sets an id and builds amd64:
Copy code
build:
  - prefect_docker.deployments.steps.build_docker_image:
      id: build_image
      image_name: us-central1-docker.pkg.dev/<PROJECT>/<REPO>/xct
      tag: latest
      platform: linux/amd64

push:
  - prefect_docker.deployments.steps.push_docker_image:
      image_name: '{{ build_image.image_name }}'
      tag: '{{ build_image.tag }}'
2) Update your deployment to use the push pool and only valid job variables:
Copy code
- name: hal-xct-pipeline-dev
  entrypoint: flows/xct_flow.py:xct_temp_alerting_pipeline
  parameters:
    current_processing_date: "2025-11-18"
  work_pool:
    name: cloud-run-work-pool
    work_queue_name: default
    job_variables:
      image: '{{ build_image.image }}'
      # Optional if not set at pool level:
      # region: "us-central1"
      # service_account_name: "prefect-cloud-run"
      # cpu: "1"
      # memory: "2Gi"
      # timeout: 3600
  schedules: []
3) Redeploy so the deployment picks up the new pool and variables:
Copy code
prefect deploy
4) Test a run:
Copy code
prefect deployment run hal-xct-pipeline-dev
If it still says Not ready - Check the pool’s default variables match Cloud Run push requirements (credentials set by provisioning, region, service account, etc.). - Verify the image actually exists and is public/accessible to the pool’s service account: - Example image path:
us-central1-docker.pkg.dev/<PROJECT>/<REPO>/xct:latest
- Confirm your build step really emits
build_image.image
. If not, hardcode the image string in
job_variables.image
and test. Tip: You can inspect the default schema for your push pool type to see exactly which variables are allowed:
Copy code
prefect work-pool get-default-base-job-template --type cloud-run:push
Docs - Serverless push pools (Cloud Run): Serverless work pools - Manage work pools (variables, provisioning): Manage work pools - Work pools overview: Work pools concept If you share your full prefect.yaml (redacting secrets), I can sanity-check the build/push outputs and the deployment section to get those deployments to Ready quickly.
d
@Marvin please outline very clearly what permissions are required for the gcp credentials block to have for this push pool!
m
thought for 198.1 seconds
Here’s the concise, least‑privilege set of GCP permissions and APIs your GCP Credentials block’s service account needs for a Cloud Run push work pool. Required IAM roles on your GCP project - roles/iam.serviceAccountUser - Allows Prefect to “act as” the runtime service account used by Cloud Run Jobs. - roles/run.developer - Create/run/manage Cloud Run Jobs (sufficient for push pools). If your org prefers broader rights, roles/run.admin also works but is more permissive. - roles/artifactregistry.reader - Pull images from Artifact Registry. If you use Prefect’s build/push steps to publish images, grant roles/artifactregistry.repoAdmin to the identity that does the push (often your CI, not the Prefect SA). Optional roles (only if you use these features) - roles/vpcaccess.user - If you set a VPC connector on the job (vpc_connector_name). - roles/cloudsql.client - If your job connects to Cloud SQL (cloudsql_instances). Required APIs to enable in the project - run.googleapis.com (Cloud Run API) - artifactregistry.googleapis.com (Artifact Registry) - vpcaccess.googleapis.com (only if using a VPC connector) - sqladmin.googleapis.com (only if using Cloud SQL) Minimal setup commands (example)
Copy code
PROJECT_ID="your-project-id"
PREFECT_SA="prefect-cloud-run@${PROJECT_ID}.<http://iam.gserviceaccount.com|iam.gserviceaccount.com>"

# Core
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$PREFECT_SA" \
  --role="roles/iam.serviceAccountUser"

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$PREFECT_SA" \
  --role="roles/run.developer"

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$PREFECT_SA" \
  --role="roles/artifactregistry.reader"

# Optional
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$PREFECT_SA" \
  --role="roles/vpcaccess.user"

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$PREFECT_SA" \
  --role="roles/cloudsql.client"

# APIs
gcloud services enable <http://run.googleapis.com|run.googleapis.com> <http://artifactregistry.googleapis.com|artifactregistry.googleapis.com> --project=$PROJECT_ID
# Optional
gcloud services enable <http://vpcaccess.googleapis.com|vpcaccess.googleapis.com> <http://sqladmin.googleapis.com|sqladmin.googleapis.com> --project=$PROJECT_ID
Notes - If you specify a separate runtime service account in the pool/deployment (
service_account_name
), the Prefect service account must have
roles/iam.serviceAccountUser
on that runtime account too (actAs). - Cloud Run requires linux/amd64 images. Make sure your image platform matches. - If provisioning via Prefect’s “Provision infrastructure” flow, most of this is created/assigned for you. References - Serverless push pools: Serverless work pools - GCP service accounts and IAM: Service accounts and IAM roles - Cloud Run docs: Cloud Run - Artifact Registry docs: Artifact Registry
d
@Marvin this is working now. Can you explain exactly where cloud run push work pool jobs actually run. They are within my GCP project infrastructure, but where can I actually observe them within my infra in GCP UI
m
thought for 62.7 seconds
They run as Google Cloud Run Jobs in your GCP project, in the region you configured on the push work pool. For each Prefect flow run, Prefect creates a Cloud Run Job and launches an Execution on-demand in your project. There is no long‑running Cloud Run Service involved. Where to observe them in the GCP Console - Cloud Run → Jobs (not Services) - Switch to the region configured on your work pool (Variables →
region
). - You’ll see Jobs created per flow run (names are generated by Prefect). - Click a Job → Executions to see each run’s status, start/end time, retries, etc. - Click into an Execution → Logs to view container logs. - Logs (Cloud Logging → Log Explorer) - Filter by the Cloud Run Job resource to see all logs for runs:
Copy code
resource.type="cloud_run_job"
  resource.labels.project_id="<PROJECT_ID>"
  resource.labels.location="<REGION>"
- Optionally filter by job name or your image name/tag. - Metrics/Monitoring - Cloud Run → Jobs shows per‑execution status and history. - Cloud Monitoring → Metrics Explorer → resource type “Cloud Run Job” for CPU/memory, execution counts, errors. Helpful CLI for quick inspection
Copy code
# List jobs in a region
gcloud run jobs list --region=<REGION>

# Describe a specific job
gcloud run jobs describe <JOB_NAME> --region=<REGION>

# List executions for a job
gcloud run jobs executions list --job=<JOB_NAME> --region=<REGION>

# Describe a specific execution
gcloud run jobs executions describe <EXECUTION_NAME> --region=<REGION>
Notes - Prefect sets the job spec from your pool/deployment variables (image, CPU/memory, timeout, service account, VPC connector, etc.). The job runs fully inside your GCP project with that runtime service account. - By default Prefect cleans up the Cloud Run Job resources it creates to avoid clutter. If you want to keep the job objects around for debugging, set
keep_job: true
in the pool/deployment job variables; otherwise use Cloud Logging to review past runs. - Your container images are pulled from your Artifact Registry repo, so you can verify the exact image/tag there as well. Docs - Cloud Run Jobs overview: Cloud Run Jobs - Serverless push pools (Prefect): Serverless work pools
d
@Marvin sorry that was no clear. I know the actual flows run in cloud run jobs. I mean where is the work pool itself ran?
m
thought for 34.5 seconds
Great question — with a Cloud Run push work pool, there is nothing “running” in your GCP for the pool itself. - What a work pool is: it’s a control‑plane object that lives in Prefect Cloud. It stores configuration (type, base job template, variables, concurrency limits) and routes flow runs. - What happens on a run: when a deployment targets your push pool, Prefect Cloud uses the GCP Credentials block to call the Cloud Run API and create a Job Execution in your GCP project/region. No worker process is started in your infra. Where you can observe things - In Prefect Cloud (control plane) - Work Pools page → your pool: status, variables, concurrency, queues - Deployments page: which deployments target the pool - Flow runs: state transitions and “Submitted to infrastructure” events - CLI:
Copy code
prefect work-pool inspect cloud-run-work-pool
    prefect work-pool preview cloud-run-work-pool --hours 24
- In GCP (data plane) - Cloud Run → Jobs: the per‑run Jobs/Executions created on demand - Cloud Logging → Log Explorer: resource.type="cloud_run_job" - IAM → Service Accounts: the service account your pool uses - Artifact Registry: your images (if you’re using your own repos) Key takeaway - Push pool = no worker to host. The pool exists only in Prefect Cloud; the only GCP resources you’ll see are the service account, Artifact Registry repo (from provisioning), and the Cloud Run Job Executions created when runs start. Docs - Work pools concept: Work pools concept - Serverless (push) pools: Serverless work pools - Manage work pools: Manage work pools
d
@Marvin with cloud run push pools, what’s the maximum amount of time a flow can run for? Is it still 1 hour?
m
thought for 110.6 seconds
Short answer: no — with Cloud Run push pools your flows run as Cloud Run Jobs, and Cloud Run Jobs can run much longer than 1 hour. - Cloud Run Jobs max execution timeout: up to 7 days (604,800 seconds) - Exception: if you use GPUs, the max is currently 1 hour - Official docs: Cloud Run Jobs task timeout Where to set it in Prefect (push pool) - The timeout is controlled by the
timeout
job variable (in seconds). You can set it: - On the work pool (Variables tab), which becomes the default for all deployments - Per deployment in your deployment config
work_pool.job_variables
Example (Prefect 2.x prefect.yaml)
Copy code
deployments:
  - name: my-deployment
    entrypoint: flows/my_flow.py:my_flow
    work_pool:
      name: cloud-run-work-pool
      job_variables:
        image: "us-central1-docker.pkg.dev/<PROJECT>/<REPO>/my-image:latest"
        timeout: 86400       # 24 hours, in seconds
        # cpu, memory, region, service_account_name, etc. can also be set here
Notes - If you set a timeout beyond Cloud Run’s limit, the Cloud Run API will reject it and you’ll see an error in your flow’s submission. - Cloud Run Services (HTTP) have a 60-minute request timeout, but push pools use Cloud Run Jobs, not Services, so the 7‑day limit applies.