Cloud Run cost tier (cloud-cheap)
The repository’s cloud-cheap tier runs DeepIntShield as one multi-container
Google Cloud Run service backed by Cloud SQL. It is intended for development,
demos, and low-traffic environments that prioritize a low idle cost and can
tolerate cold starts.
Architecture
Section titled “Architecture”One Cloud Run revision contains four containers that share a network namespace:
| Component | Role | Persistence |
|---|---|---|
| server | HTTP ingress on port 8080; gateway and embedded regex/Rego guard runtime | Application state in Cloud SQL |
| models | ML detectors on localhost; Hugging Face cache mounted from GCS with gcsfuse | Model weights in the GCS bucket |
| redis | Response/semantic cache sidecar | Ephemeral; not a system of record |
| openfga | Required relationship-authorization service on localhost port 8082 | Separate OpenFGA database/user in Cloud SQL |
The app database and OpenFGA database share one managed PostgreSQL instance but use separate databases and users. Authorization stores, authorization models, and tuples therefore survive scale-to-zero, revisions, and additional Cloud Run instances.
Prerequisites
Section titled “Prerequisites”- A Google Cloud project with billing enabled and
gcloudauthenticated. - Permission to create Cloud Run services/jobs, Cloud SQL, Artifact Registry, Secret Manager secrets, a GCS bucket, service accounts, and IAM bindings.
- A globally unique model-cache bucket name.
- A public DNS hostname that can be mapped to Cloud Run.
- Docker for local native-amd64 builds, or Cloud Build access.
Deploy from the repository
Section titled “Deploy from the repository”Run these commands from the repository root:
-
Create the deployment environment file.
Terminal window cp deployment/tiers/cloud-cheap/env.example \deployment/tiers/cloud-cheap/.envSet at least
PROJECT_ID,REGION, globally uniqueMODELS_BUCKET,CLOUDSQL_PASSWORD,PUBLIC_HOSTNAME, SMTP values, andDEPLOYER_MEMBER.PUBLIC_HOSTNAMEis a hostname only—no scheme, port, wildcard, or path. -
Bootstrap shared resources once.
Terminal window ./deployment/tiers/cloud-cheap/scripts/bootstrap_cloudrun.shThe script creates the app and OpenFGA Cloud SQL databases/users, model bucket, runtime service account, and required IAM bindings. It also creates independent stable encryption and OpenFGA database-password secrets when they do not already exist.
-
Build and push the images.
Terminal window ./deployment/tiers/cloud-cheap/scripts/build_and_push.shThe target is
linux/amd64. On Apple silicon or another arm64 host, leaveBUILD_BACKEND=autoso the script selects native-amd64 Cloud Build. Ordinary QEMU emulation can crash the Go runtime duringgo mod download; that crash is not evidence thatgo.modorgo.sumshould change. -
Provision OpenFGA, migrate, and deploy.
Terminal window ./deployment/tiers/cloud-cheap/scripts/deploy_cloudrun.shDeployment runs idempotent OpenFGA database provisioning and a version-matched schema migration job before replacing the service. The OpenFGA image is pinned by immutable digest.
-
Verify the deployed revision.
Terminal window ./deployment/tiers/cloud-cheap/scripts/smoke_test.shThe smoke test validates the deployed manifest, required OpenFGA startup dependency, persistent datastore wiring, cache policy, scaling values, health endpoint, and the GAF-enabled startup record. It allows several minutes for a cold start.
Map PUBLIC_HOSTNAME to the Cloud Run service and publish the DNS records that
Google provides. If an organization policy blocks an anonymous run.invoker
binding, the deployment can still be tested through an authenticated Cloud Run
proxy, but public gateway clients will not reach it until that policy is
resolved.
OpenFGA and the canonical MCP boundary
Section titled “OpenFGA and the canonical MCP boundary”OpenFGA is not optional in this tier:
AGENTICNEW_GAF_REQUIRED=truemakes the server fail startup instead of serving protected routes without a database-ready authorizer.- Cloud Run starts the server only after the OpenFGA
/healthzstartup probe succeeds. - Legacy ReBAC and Agentic-New GAF use separate stores on the same durable OpenFGA database.
- OpenFGA query/iterator caches and the process-local GAF Allow cache are disabled, so a stale revision-local Allow cache cannot hide a revocation from the next check.
JSON-RPC /mcp, POST /v1/mcp/tool/execute, Agent Mode, and nested Code Mode
calls use the same canonical GAF enforcement point. Every actual invocation
requires an exact Allow. A dependency or durable-audit failure blocks execution
instead of falling back to an ungoverned path.
Disabling caches does not synchronously terminate every in-flight operation on every replica. An OAuth status/generation or relationship change is enforced on the next acquisition, decision, or reconciliation; an already leased call may drain. See Relationship Authorization and MCP tool execution.
OAuth 2.1 deployment identity
Section titled “OAuth 2.1 deployment identity”The manifest derives APP_BASE_URL=https://<PUBLIC_HOSTNAME> from deployment
configuration. That stable public origin owns both:
/api/oauth/callback; and- the exact public GET
/api/oauth/client-metadata.jsonused for deployment- owned Client ID Metadata Document registration.
The request Host and forwarded headers cannot choose these identifiers. Keep
the generated DEEPINTSHIELD_ENCRYPTION_KEY stable on every revision: strict
OAuth 2.1 refuses initiation without it, and uncoordinated rotation makes
persisted client secrets, PKCE verifiers, tokens, and pending configurations
unreadable. The deployment scripts reuse the enabled Secret Manager version and
do not rotate it automatically.
For registration priority, issuer/resource binding, reauthorization, and revocation behavior, see MCP OAuth 2.1 and OAuth 2.0.
Cost, scaling, and latency
Section titled “Cost, scaling, and latency”The defaults are deliberately cost-first:
CLOUD_RUN_MIN_INSTANCES=0CLOUD_RUN_MAX_INSTANCES=1CLOUD_RUN_CONCURRENCY=40CLOUDSQL_TIER=db-f1-microMIN_INSTANCES=0removes idle Cloud Run compute but retains the standing Cloud SQL, GCS, Artifact Registry, and networking costs. Verify current regional prices with the Google Cloud calculator; a fixed monthly total is not guaranteed.- Set
MIN_INSTANCESto at least 1 to reduce idle cold starts, accepting the additional compute cost. New revisions and scale-out can still cold-start. - Raise
MAX_INSTANCESand tune concurrency for horizontal scaling only after upgrading Cloud SQL. The shareddb-f1-microapp/OpenFGA instance is the primary bottleneck. - Redis caches and delegated Streamable HTTP session pools are replica-local. Scale-out can cause a cache miss or a fresh token exchange/initialization; use load-balancer stickiness when a workflow depends on one long-lived MCP session. Durable binding/status checks still run before a warm session is acquired.
- Each streaming request is bounded by Cloud Run’s configured 3,600-second ceiling; provider, gateway, and client timeouts may end it sooner.
- OpenFGA checks, policy work, instrumentation, cache misses, and upstream tools retain measurable workload-dependent latency. Benchmark with expected concurrency, policies, failures, and MCP session behavior.
Cold-start security behavior
Section titled “Cold-start security behavior”The models container synchronously preloads configured ML detectors before it opens port 8093, while the ingress server starts in parallel. Until the models port is ready, this tier’s ML guardrail calls are configured fail-open; embedded regex and Rego checks continue to run. The GCS mount avoids repeatedly downloading warmed weights, but it does not eliminate process/model startup.
If fail-open ML warmup is unacceptable, keep instances warm and validate model readiness before traffic, or use an always-on deployment designed for that availability requirement.
Operations notes
Section titled “Operations notes”- Cloud SQL is the system of record. Export both the app and OpenFGA databases before a migration or teardown.
- The OpenFGA database password is another stable Secret Manager value. The scripts reuse it and do not rotate it automatically; coordinate password rotation with the database and every revision.
- The local filesystem and Redis sidecar are ephemeral. Durable webhook payloads require an external S3-compatible object store.
- Langfuse export is optional; OpenFGA/GAF is required.
- The
production-cheapCI environment follows the same build, provision, migration, deploy, and smoke sequence as the manual scripts.
Next steps
Section titled “Next steps”- Deployment options — compare this reference tier with hosted, Enterprise VPC, and self-hosted deployments.
- Relationship Authorization — model and test the required OpenFGA permissions.
- MCP OAuth 2.1 — configure shared OAuth and delegated MCP authentication.