AFFiNE on Google Cloud Run
AFFiNE is an open-source, privacy-first knowledge base that unifies docs, whiteboards, and databases in one workspace — a self-hostable alternative to Notion and Miro. This module deploys AFFiNE on Cloud Run v2 on top of the App_CloudRun foundation, which provisions and manages the shared Google Cloud infrastructure.
This guide focuses on the cloud services AFFiNE uses and how to explore and operate them from the Google Cloud Console and the command line. For the mechanics common to every Cloud Run application — service identity, ingress and load balancing, scaling and concurrency, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC Service Controls, backups, and the deployment lifecycle — refer to the App_CloudRun foundation guide rather than repeating them here.
What AFFiNE costs on RAD, and how that compares
AFFiNE on RAD's Cloud Run module costs about US$181 a month in a project you own, with no licence fee for the software itself. RAD charges a one-off module fee of 300 credits (US$30 at the top-up price) in a project you own, and 270 credits (10% lower) in a project RAD manages. If AFFiNE needs to run continuously across pods or beside other Kubernetes workloads, see the GKE guide instead. Figures are as at 8 October 2026; sources are listed at the end of this section.
If you only need it occasionally — studying for a certification, a demo, a seasonal need — a RAD-managed project can be deleted and restored within 30 days for a handful of credits, so that about US$181 a month becomes close to nothing instead. See Pause it for free, below.
What you pay on RAD
You pay for three things:
| In a Google Cloud project you own | In a project RAD manages for you | |
|---|---|---|
| Module fee, once per deployment | 300 credits (US$30 at the top-up price) | 270 credits (10% lower) |
| Build time | A few credits, metered per minute of build time | The same |
| Google Cloud running cost | Billed by Google to your own billing account, about US$181 a month for the default configuration (table below) | Metered hourly in credits; RAD publishes 83 credits a day, about 2,490 a month (about US$249 at the top-up price, US$199 at the Scale plan's rate) |
| Who owns what | You own the project and its billing; RAD deploys and updates it | RAD owns the project, with guardrails, quotas and budget alerts; you get console access, and a minimum purchased balance is held in reserve |
10 credits cost US$1 on a one-off top-up, and less on a monthly plan. In a project RAD manages, the database and file/cache server are shared by every application in the project, so a second application does not add a second one.
Default running cost in your own project (us-central1, Google list prices):
| Resource (module default) | Per month |
|---|---|
| Cloud Run, 2x vCPU / 4 GiB (alwaysOn) | US$110.42 |
| Cloud SQL for PostgreSQL, 1 vCPU / 3.75 GB, zonal, 10 GB SSD | US$51.02 |
| NFS/cache file server (small VM) | US$13.43 |
| Cloud NAT and networking | US$5 |
| Cloud Storage (add-ons, backups) | US$1 |
| Total | about US$181 |
How it compares
- Notion, the incumbent AFFiNE is built to replace, charges £8.50/member/month on its Plus plan and £16.50/member/month on Business — a per-seat licence that keeps growing with headcount, against AFFiNE's flat infrastructure cost here.
- RAD runs the open-source project itself, not a vendor's hosted tenancy. You get the same software, under your own (or RAD's) infrastructure, instead of a per-seat or per-usage subscription that grows independently of what you actually use.
- Against a bare self-managed server: Running the same open-source software yourself, a Hetzner CPX22 (2 vCPU/4 GB, about $24/month) or a DigitalOcean 2 vCPU/4 GB Droplet (also $24/month) is roughly the same shape; a GCP Compute Engine e2-standard-2 (2 vCPU/8 GB) runs about $49/month. RAD is not cheaper than that in cash terms — the difference is the managed database, Secret Manager and monitoring that come with the module instead of being your own job.
Pause it for free: delete a RAD-managed project, restore it when you need it
If AFFiNE runs in a project RAD manages for you, you have an option that goes well beyond scaling to zero: delete the whole project, and restore it within 30 days for close to nothing. This suits occasional use — studying for a certification, a demo, a seasonal need — far better than running AFFiNE continuously.
- How it works. Deleting a RAD-managed project unlinks its billing first, then asks Google to delete the project outright. Google does not remove it immediately: it keeps the project, recoverable, for 30 days, and because billing is already unlinked nothing is charged while it waits. Unlike deleting one module, this does not tear down the database, any VM or the compute resource one by one — the whole project simply stops, and nothing is billed in the meantime.
- Restoring costs a handful of credits, not a rebuild. Within 30 days, only the project's owner can restore it. RAD asks Google to undelete the project and reattaches its billing account, then asks you to run Update on each deployment to confirm everything came back. Because nothing was individually destroyed, that Update finds the same resources already there — it is a check, not a rebuild, and an Update never charges the module fee again. This costs only a handful of credits in total (under US$1), against paying the module fee and a full build again.
- What this needs. You must own the project (not one RAD only manages billing for), you must restore it yourself within the 30 days — after that Google deletes it for good — and restoring is admitted like creating a new project, so your purchased credit balance must still clear the tier's floor (100 credits for the sandbox tier most study and demo use fits). Google says most services are fully working again within 36 hours of a restore.
- One real gap: backups do not survive. Anything AFFiNE writes to a backup bucket inside the project is very likely gone as soon as you delete the project, even though the project itself is recoverable for 30 days — that bucket has Cloud Storage's soft-delete explicitly turned off. Anyone who has customised the deployment and wants to keep that work should copy a backup out (to Google Drive, or a bucket outside the project) before deleting. For a default install with nothing irreplaceable in it, this does not matter.
Pay only while you use it, the other way: delete and redeploy
This is the fallback for a project you own, or once the 30-day restore window above has passed: delete the deployment, and deploy it again when you next need it.
- What a redeploy costs. The module fee again, plus the builds: roughly 305 credits (about US$30.50) in your own project, or 275 credits in a RAD-managed one, because RAD rebuilds the resources from scratch. Deleting saves money once AFFiNE would otherwise sit unused long enough to clear that redeploy cost against its own running cost — roughly 5 days or more in your own project (US$6.03/day) or 3 days or more in a RAD-managed one (83 credits/day).
- Most of the running cost is usually shared infrastructure. The database and file or cache VM stop only when nothing else in the project uses them, so deleting AFFiNE while another application shares the project saves only AFFiNE's own compute part.
- Keep your data first. Anything AFFiNE writes to a backup bucket inside the deployment is deleted with it — copy the latest backup out (to Google Drive, or a bucket you keep) before deleting if you want to keep it.
- RAD does not recreate a deleted deployment for you. You enter the settings again when you redeploy.
Lab sessions and Managed Environments
- Lab sessions, for training. A trainer runs a session for a class. Each participant gets AFFiNE in their own Google Cloud project for 15 minutes to 24 hours, within an allowance the trainer sets. Either the trainer funds every place, or each participant pays for their own. Everything is deleted when the session ends and unused credits go back to the trainer.
- Managed Environments, for consultancies. A partner runs AFFiNE for a client from a ring-fenced wallet it funds, and settles with the client directly. If the wallet runs low, billing pauses and the data is kept, so nobody receives an unexpected charge. At the end the partner hands the project over and the deployments become the client's own.
Credits can be bought in more than 20 currencies, including XAF, XOF, NGN, GHS, KES and ZAR, by card, bank transfer or mobile money.
Sources (8 October 2026): Google Cloud list prices from the Cloud Billing Catalog API; RAD's fees and daily-credit estimate from radmodules.dev/pricing; Delete and restore projects for the pause/restore mechanics; Notion pricing. Prices change; check each source before relying on a figure.
1. Overview
AFFiNE's self-host server runs as a single Node.js container on Cloud Run v2. The deployment wires together a focused set of Google Cloud services:
| Capability | Google Cloud service | Notes |
|---|---|---|
| Compute | Cloud Run v2 | Node.js service, 2 vCPU / 4 GiB by default, single always-on instance |
| Database | Cloud SQL for PostgreSQL 15 | Required — AFFiNE does not support MySQL (enforced at plan time) |
| Real-time collaboration | Redis | Mandatory — Yjs document-sync pub/sub and the job queue; the NFS host co-hosts the default Redis |
| Blob storage | Filestore / NFS | Uploaded attachments persisted at /root/.affine/storage (gen2 required) |
| Object storage | Cloud Storage | A dedicated storage bucket provisioned automatically |
| Secrets | Secret Manager | Database password managed automatically; AFFiNE needs no app secret |
| Container image | Cloud Build + Artifact Registry | Thin custom build over ghcr.io/toeverything/affine |
| Ingress | Cloud Run URL / Cloud Load Balancing | Default run.app URL, optional external HTTPS LB + custom domain |
Sensible defaults worth knowing up front:
- PostgreSQL 15 is mandatory. A plan-time validation restricts
database_typeto PostgreSQL versions; MySQL is rejected. - Redis is mandatory. A plan-time validation fails the deploy if
enable_redis = false. With no explicitredis_host, the NFS server IP is used as the Redis endpoint. - Single instance by design.
min_instance_count = 1,max_instance_count = 1,cpu_always_allocated = true— real-time collaboration WebSockets must stay reachable and CPU-fed, and per-process collab state plus filesystem blobs make horizontal scaling unsafe. - No Cloud SQL socket.
enable_cloudsql_volume = false: AFFiNE consumes a URL-authorityDATABASE_URLthat cannot carry the socket path's colons, so the entrypoint connects over the instance private IP withsslmode=require. - Two init jobs on apply.
db-initidempotently creates the database and user;affine-migrateruns AFFiNE'sself-host-predeploy(schema migration + signing-key generation) before the server starts. - No application secret. AFFiNE persists its own signing key in PostgreSQL during migration; only the auto-generated database password lives in Secret Manager.
- Health probes target
/— AFFiNE returns HTTP 200 on its root path once ready. application_version = "latest"maps tostable— AFFiNE publishes nolatestimage tag.- Full-text/vector search is disabled (
AFFINE_INDEXER_ENABLED = "false") — the indexer needs a vector backend not provisioned here.
2. Google Cloud Services & How to Explore Them
All commands assume PROJECT and REGION are set. Service and resource names are reported in the deployment Outputs.
A. Cloud Run — the AFFiNE service
AFFiNE runs as a Cloud Run v2 service pinned to a single always-on instance. Each deployment creates an immutable revision; traffic moves to the newest healthy one.
- Console: Cloud Run → select the service for revisions, traffic, logs, and metrics.
- CLI:
gcloud run services list --project "$PROJECT" --region "$REGION"
gcloud run services describe <service-name> --project "$PROJECT" --region "$REGION"
gcloud run revisions list --service <service-name> --project "$PROJECT" --region "$REGION"
See App_CloudRun for scaling, concurrency, execution environment, and traffic splitting.
B. Cloud SQL for PostgreSQL 15
AFFiNE stores workspaces, documents, users, and its own signing key in a managed Cloud SQL for PostgreSQL 15 instance. Because AFFiNE's DATABASE_URL is a URL-authority DSN, the service connects over the private IP with TLS (sslmode=require) rather than the Auth Proxy socket. On first deploy the db-init job creates the application database and user, then affine-migrate creates the schema.
- Console: SQL → select the instance for connections, backups, flags, metrics.
- CLI:
gcloud sql instances list --project "$PROJECT"
gcloud sql instances describe <instance-name> --project "$PROJECT"
gcloud sql connect <instance-name> --user=<db-user> --project "$PROJECT"
The instance name, database, user, and password secret are in the Outputs. See App_CloudRun for the connection model, backups, and password rotation.
C. Redis — real-time collaboration
Redis carries AFFiNE's Yjs document-sync pub/sub and its background job queue — the deployment refuses to plan without it. When no external redis_host is configured, the shared NFS server's co-hosted Redis is used automatically.
- Console: Memorystore → Redis (if using a managed instance); Compute Engine → VM instances (the NFS/Redis host).
- CLI:
redis-cli -h <redis-host> ping
redis-cli -h <redis-host> info clients
D. Filestore (NFS) and Cloud Storage
Uploaded blobs (images, attachments, file embeds) are written to an NFS share mounted at /root/.affine/storage, so they survive revisions and restarts. A dedicated Cloud Storage bucket (suffix storage) is also provisioned automatically. The gen2 execution environment is required for NFS mounts.
- Console: Filestore → Instances (or Compute Engine → VM instances for the self-managed NFS VM); Cloud Storage → Buckets.
- CLI:
gcloud filestore instances list --project "$PROJECT"
gcloud storage buckets list --project "$PROJECT"
gcloud storage ls gs://<storage-bucket>/ # bucket name is in the Outputs
See App_CloudRun for the NFS mount, GCS Fuse, and CMEK.
E. Secret Manager
The auto-generated database password is the only secret — AFFiNE generates and stores its signing key inside PostgreSQL during the affine-migrate job, so no application secret exists to manage or rotate.
- Console: Security → Secret Manager.
- CLI:
gcloud secrets list --project "$PROJECT"
gcloud secrets versions access latest --secret=<secret-name> --project "$PROJECT"
See App_CloudRun for injection and rotation details.
F. Networking & ingress
The service is reachable at its run.app URL by default. An external HTTPS load balancer with a custom domain, Cloud CDN, and Cloud Armor can be layered on; ingress settings and VPC egress control connectivity. The cloud entrypoint defaults AFFINE_SERVER_EXTERNAL_URL to the injected service URL so invites and share links resolve correctly.
- Console: Cloud Run (service URL); Network services → Load balancing.
- CLI:
gcloud run services describe <service-name> --region "$REGION" --format='value(status.url)'
gcloud compute addresses list --project "$PROJECT"
See App_CloudRun.
G. Cloud Logging & Monitoring
Container logs flow to Cloud Logging; Cloud Run and Cloud SQL metrics flow to Cloud Monitoring, with optional uptime checks and alert policies.
- Console: Logging → Logs Explorer; Monitoring → Dashboards / Alerting.
- CLI:
gcloud run services logs read <service-name> --project "$PROJECT" --region "$REGION" --limit 50
3. AFFiNE Application Behaviour
- Two-stage database setup. On apply,
db-init(imagepostgres:15-alpine) idempotently creates the AFFiNE role and database, grants privileges, and best-effort grantscloudsqlsuperuserso migrations canCREATE EXTENSION. Thenaffine-migrateruns AFFiNE'snode ./scripts/self-host-predeployusing the built app image — idempotent schema migration plus signing-key generation. Both are safe to re-run;affine-migrateretries up to 3 times. - Signing key lives in the database. Unlike most apps there is no
APP_SECRET-style env var: the key generated byself-host-predeployis persisted in PostgreSQL, so the deployment carries no application secret to desync or rotate. - DSN assembly at startup. The cloud entrypoint builds
DATABASE_URLfrom the Foundation-injectedDB_*vars (URL-encoding the credentials) and mapsREDIS_HOST/PORT/AUTHto AFFiNE'sREDIS_SERVER_*. On Cloud Run it connects to the Cloud SQL private IP withsslmode=require; a presetDATABASE_URLenv var takes precedence. - External URL.
AFFINE_SERVER_EXTERNAL_URLdefaults to the Cloud Run service URL. Set it explicitly (viaenvironment_variables) once a custom domain is live so share links and invite emails use the right host. - First-run setup. Open the service URL and create the first account — on a fresh AFFiNE self-host instance the first registered user becomes the server administrator, and the admin panel is at
<url>/admin. - Health path. Startup, liveness, and readiness probes target
/, which returns HTTP 200 once the server is ready (startup window: 60 s initial delay + up to 30 × 15 s). - Scaling constraint. The service is pinned to exactly one always-on instance. Blobs on the NFS filesystem and per-process Yjs state make multiple instances unsafe; scale vertically (
cpu_limit/memory_limit) instead. - Verification:
SERVICE=$(gcloud run services list --project "$PROJECT" --region "$REGION" \
--filter="metadata.name~affine" --format="value(metadata.name)" --limit=1)
SERVICE_URL=$(gcloud run services describe "$SERVICE" --project "$PROJECT" \
--region "$REGION" --format="value(status.url)")
curl -s -o /dev/null -w "%{http_code}\n" "$SERVICE_URL/" # expect 200
4. Configuration Variables
Variables are grouped exactly as they appear on the deployment platform. Only settings specific to or notable for AFFiNE are listed; every other input is inherited from App_CloudRun with its standard behaviour.
Group 1 — Project & Identity
| Variable | Default | Description |
|---|---|---|
project_id | (required) | Target Google Cloud project. |
region | us-central1 | Region for the service and regional resources. |
Group 2 — Deployment Environment
| Variable | Default | Description |
|---|---|---|
tenant_id | demo | Short suffix that makes resource names unique per environment. |
support_users | [] | Emails granted IAM access and monitoring alerts. |
All other inputs follow standard App_CloudRun behaviour.
Group 3 — Application Identity
| Variable | Default | Description |
|---|---|---|
application_name | affine | Base name for resources. Do not change after first deploy. |
application_version | stable | Image tag for ghcr.io/toeverything/affine; latest maps to stable. Increment to trigger a rebuild and new revision. |
All other inputs follow standard App_CloudRun behaviour.
Group 4 — Runtime & Scaling
| Variable | Default | Description |
|---|---|---|
cpu_limit / memory_limit | 2000m / 4Gi | AFFiNE needs at least 2Gi for reliable operation. |
container_port | 3010 | AFFiNE's native self-host server port. |
min_instance_count | 1 | Keeps the collaboration WebSocket server always reachable — scale-to-zero drops live editing sessions. |
max_instance_count | 1 | Pinned. Blobs on the filesystem + per-process collab state make horizontal scaling unsafe. |
cpu_always_allocated | true | WebSocket Yjs sync is starved under request-based CPU throttling — keep true for a live collaborative editor. |
enable_cloudsql_volume | false | AFFiNE's URL-authority DATABASE_URL cannot carry the Cloud SQL socket path; the entrypoint uses the private IP with sslmode=require. |
container_image_source | custom | The thin-wrapper build supplies the cloud entrypoint — required. |
execution_environment | gen2 | Required for the NFS mount. |
All other inputs follow standard App_CloudRun behaviour.
Group 6 — Environment Variables & Secrets
| Variable | Default | Description |
|---|---|---|
environment_variables | {} | Merged over the Affine_Common defaults (NODE_ENV, AFFINE_SERVER_HOST/PORT, AFFINE_CONFIG_PATH, AFFINE_INDEXER_ENABLED=false). Never set PORT — it is a Cloud Run reserved name and breaks Job creation. |
secret_environment_variables | {} | AFFiNE needs no application secret by default. |
All other inputs follow standard App_CloudRun behaviour.
Group 11 — Storage & Filesystem
| Variable | Default | Description |
|---|---|---|
enable_nfs | true | Blob storage and the default Redis host. Keep true unless an external redis_host is supplied. |
nfs_mount_path | /root/.affine/storage | Where AFFiNE persists uploaded blobs. |
All other inputs follow standard App_CloudRun behaviour. The storage GCS bucket is always provisioned by Affine_Common.
Group 12 — Database Backend
| Variable | Default | Description |
|---|---|---|
database_type | POSTGRES_15 | AFFiNE requires PostgreSQL — MySQL is rejected at plan time. |
db_name / db_user | affine / affine | Immutable after first deploy. |
All other inputs follow standard App_CloudRun behaviour.
Group 13 — Jobs & Scheduled Tasks
| Variable | Default | Description |
|---|---|---|
initialization_jobs | [] | Leave empty for the built-in db-init (postgres:15-alpine) + affine-migrate (built app image) jobs. |
All other inputs follow standard App_CloudRun behaviour.
Group 14 — Observability & Health
| Variable | Default | Description |
|---|---|---|
startup_probe | HTTP /, 60 s delay, 30 failures | Generous first-boot window. |
liveness_probe | HTTP /, 60 s delay | Root path returns 200 once ready. |
uptime_check_config | disabled, path / | Cloud Monitoring uptime check. |
All other inputs follow standard App_CloudRun behaviour.
Group 21 — Redis
| Variable | Default | Description |
|---|---|---|
enable_redis | true | Mandatory — plan-time validation rejects false. Yjs pub/sub + job queue. |
redis_host | "" | Leave empty to use the NFS host IP. |
All other inputs follow standard App_CloudRun behaviour.
Group 22 — VPC Service Controls
All inputs follow standard App_CloudRun behaviour (enable_vpc_sc, vpc_cidr_ranges, vpc_sc_dry_run, organization_id, enable_audit_logging).
5. Outputs
Returned on a successful deployment — the quickest way to locate and explore the running resources.
| Output | Description |
|---|---|
service_name | Cloud Run service name. |
service_url | Default run.app URL of the service. |
service_location | Region the service runs in. |
stage_services | Stage-specific service URLs (Cloud Deploy). |
load_balancer_ip / load_balancer_url | External HTTPS load balancer IP / URL (when enabled). |
database_instance_name | Cloud SQL instance name. |
database_name / database_user | Application database name / user. |
database_password_secret | Secret Manager secret holding the DB password. |
database_host / database_port | DB endpoint / port (host is sensitive). |
storage_buckets | Created Cloud Storage buckets (includes the AFFiNE storage bucket). |
network_name / network_exists / regions | VPC network, presence, regions. |
container_image / container_registry | Deployed image and Artifact Registry repo. |
monitoring_enabled / monitoring_notification_channels / uptime_check_names | Monitoring status, channels, uptime checks. |
initialization_jobs | Names of the setup jobs (db-init, affine-migrate). |
deployment_id / tenant_id / resource_prefix | Naming identifiers. |
project_id / project_number | Project identifiers. |
cicd_enabled / github_repository_url / github_repository_owner / github_repository_name / cicd_configuration | CI/CD status and details. |
artifact_registry_repository / cloudbuild_trigger_name / cloudbuild_trigger_id | Registry and build trigger. |
vpc_sc_enabled / vpc_sc_perimeter_name / vpc_sc_dry_run_mode | VPC-SC status. |
audit_logging_enabled / artifact_registry_cmek_enabled | Audit logging and CMEK status. |
6. Configuration Pitfalls & Sensible Defaults
Cross-variable validation runs at plan time (validation.tf): it enforces PostgreSQL, mandatory Redis with a resolvable host, min ≤ max instance counts, and rejects a Cloud SQL volume with database_type = "NONE" — misconfigurations fail fast instead of producing a broken deployment.
Risk: Critical (data loss / outage / security) — High (service degraded) — Medium (cost or partial degradation) — Low (minor).
| Setting | Sensible value | Risk | Consequence if wrong |
|---|---|---|---|
database_type | POSTGRES_15 | Critical | AFFiNE requires PostgreSQL; MySQL is rejected at plan time. |
db_name / db_user | set once | Critical | Immutable after first deploy; renaming recreates the DB/user and destroys all workspaces. |
enable_redis | true | Critical | Mandatory — real-time collaboration and the job queue need Redis; false fails the plan. |
redis_host | "" (NFS) or explicit | Critical | Redis on with NFS off and no host set fails validation; a wrong host breaks doc sync at runtime. |
enable_nfs | true | Critical | Without NFS, uploaded blobs land on ephemeral disk and vanish on every revision/restart — and the default Redis host disappears. |
container_port | 3010 | Critical | AFFiNE's native port; a mismatch fails every health probe. |
max_instance_count | 1 | Critical | More than one instance splits per-process collab state and filesystem blobs — silent data divergence. |
container_image_source | custom | High | The upstream image lacks the entrypoint that assembles DATABASE_URL / REDIS_SERVER_* — the server cannot reach its database. |
enable_cloudsql_volume | false | High | The socket path's colons break AFFiNE's URL parser (invalid port); keep private-IP + sslmode=require. |
cpu_always_allocated | true | High | Request-based throttling starves the Yjs WebSocket sync between requests — live editing stalls. |
min_instance_count | 1 | High | Scale-to-zero drops active collaboration sessions and adds cold-start delays. |
memory_limit | 4Gi (≥ 2Gi) | High | Node.js OOM during document sync or migration below 2Gi. |
environment_variables PORT | never set | High | PORT is Cloud Run-reserved; setting it makes every Job creation fail with HTTP 400. |
application_version | stable (pinned tag) | Medium | Nonexistent tags (e.g. literal latest) fail the image build; the module maps latest → stable. |
execution_environment | gen2 | High | NFS mounts require gen2. |
AFFINE_SERVER_EXTERNAL_URL | service URL / custom domain | Medium | Wrong host breaks invite links and share URLs. |
For the foundation behaviour referenced throughout — service identity, scaling and concurrency, ingress and load balancing, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC-SC, backups, and image mirroring — see App_CloudRun. AFFiNE-specific application configuration shared with the GKE variant is described in Affine_Common.
Related guides
- Hands-on lab: AFFiNE on Cloud Run — deploy it step by step, with the console screens and commands at each stage.
- AFFiNE on GKE Autopilot — the same application on Kubernetes, for when you need the other deployment target.
- AFFiNE Common — Shared Application Configuration — the configuration shared by both deployment targets.
- Deployed alongside Penpot on Google Cloud Run, Excalidraw on Google Cloud Run in the Design & Visual Collaboration solution.
Need RAD to do something it does not do yet? Request it on the roadmap, or vote on what is already there.