[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6D1WA8MP32NS1MNDF101TA2":3,"skill-same:01M6D1WA8MP32NS1MNDF101TA2":68},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":45,"commitSha":46,"skillDirectory":47,"forksCount":48,"repositoryHtmlUrl":49,"repositoryHomepageUrl":50,"ownerHtmlUrl":51,"ownerBlogUrl":50,"ownerDescription":52,"updatedAt":53,"install":54,"resources":67},"01M6D1WA8MP32NS1MNDF101TA2","devops-platforms",null,"Choosing and using a hosting platform: static and frontend hosts, container PaaS, self-hosted PaaS like Coolify, serverless functions and their limits, the big clouds' container services, managed databases, and what each costs in cold starts, regions, persistent disks, WebSockets and lock-in. Read before choosing where an app runs or configuring a platform.","enowdev\u002Fenowxcli","enowdev","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F179420349?v=4","01M6D1MVX2KC0X3Z9NESE7P22K","Enow Dev.","01M6D1MW1FMZGBDKWAJY4GQX81",67,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fdevops-platforms\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"devops","devops platforms","frontend","services","serverless","read","container","coolify","paas","self-hosted","databases","hosting","functions","self","platform","websockets","2026-11-10 10:12:30",false,"---\nname: devops-platforms\ndescription: \"Choosing and using a hosting platform: static and frontend hosts, container PaaS, self-hosted PaaS like Coolify, serverless functions and their limits, the big clouds' container services, managed databases, and what each costs in cold starts, regions, persistent disks, WebSockets and lock-in. Read before choosing where an app runs or configuring a platform.\"\n---\n\n# Hosting platforms\n\nThe generated choice is whatever the tutorial used: a WebSocket server on\nserverless functions that cannot hold a socket, a queue worker on a free tier\nthat sleeps after fifteen minutes, the app in one continent and its database\nin another, SQLite on a disk that vanishes on every deploy, Kubernetes for one\nservice run by one person, and an egress bill nobody expected. This is how to\nmatch the app's shape (stateless or stateful, requests or long-running work,\none region or several) to a platform, and the settings each one needs. One\npart of devops; the whole is in the `devops` skill.\n\n## 1. Choosing\n\n| The app | Default | Also good | Not |\n|---|---|---|---|\n| Static site, SPA, docs | Cloudflare (Workers static assets or Pages), Netlify, Vercel | Object storage behind a CDN | A server for static files |\n| SSR framework (Next.js, Nuxt, SvelteKit) | Vercel for Next.js, Netlify, Cloudflare | A container on Fly, Render, Cloud Run, Coolify | |\n| Stateless API or web app in a container | Cloud Run, Fly.io, Render, Railway | ECS Express Mode, Azure Container Apps, Coolify | |\n| WebSockets, long streams, queue workers | Fly.io, Render, Railway, Coolify, ECS on Fargate | Cloudflare Durable Objects; Cloud Run within its 60-minute request limit | Serverless functions |\n| A persistent disk (SQLite, files, an index) | Fly volume, Render disk, Railway volume, a VPS | Move the state to Postgres and object storage | Hosts with ephemeral disks |\n| Spiky, event-driven glue | AWS Lambda, Cloudflare Workers, Vercel Functions | Cloud Run jobs | Idle always-on containers |\n| Many services and teams, compliance | ECS on Fargate, managed Kubernetes (`devops-kubernetes`) | | A self-managed cluster |\n| Small budget, several small apps | A VPS (Hetzner, OVH, DigitalOcean) with Coolify or Kamal | Dokku | Hand-built, unpatched servers |\n\nWeigh, in order: the state the app keeps (disks, sockets, long jobs); where\nits data lives (app and database in the same region: a cross-region query\ncosts 50 to 200ms and more, every time); traffic shape (steady, spiky, idle\nmost of the day); who patches and is on call; cost at rest and at ten times\nthe traffic, including egress and per-seat pricing; data residency and\ncompliance reports; and lock-in (a container, Postgres and the S3 API move in\na day, platform-specific stores and runtimes take a rewrite).\n\n## 2. Frontend and function limits\n\n- Build settings live in the repository (`vercel.json`, `netlify.toml`,\n  `wrangler.jsonc`) with the Node version pinned, not only in a dashboard.\n- Variables per environment (production, preview, development). Anything\n  prefixed `NEXT_PUBLIC_` or `VITE_` is compiled into the bundle and public.\n- Previews for every PR, protected (Vercel Deployment Protection, Cloudflare\n  Access) when the app is not public.\n\n| | Vercel Functions | Cloudflare Workers | AWS Lambda |\n|---|---|---|---|\n| Duration | 300s default; up to 800s on Pro and Enterprise | No wall limit while the client is connected; CPU 10ms on Free, 30s default and 5 min maximum on paid | 15 min |\n| Memory | 2 GB (4 GB on Pro) | 128 MB per isolate | Up to 10,240 MB |\n| Request body | 4.5 MB | 100 MB on Free and Pro zones | 6 MB synchronous (streamed responses up to 200 MB) |\n| WebSockets | Public beta | Yes, through Durable Objects | Through API Gateway WebSocket APIs |\n| Node APIs | Full Node | Partial, with the `nodejs_compat` flag | Full |\n\n- Edge runtimes start in milliseconds near the user, but the database sits in\n  one region, so edge code that queries it pays the round trip on every\n  query. Default to the Node runtime in the database's region; keep edge for\n  redirects, headers, auth checks and cached reads. Vercel runs functions in\n  `iad1` unless told otherwise.\n- Cold starts: close to none for Workers isolates, hundreds of milliseconds\n  to seconds for Lambda with large bundles or a JVM (SnapStart helps). Keep\n  bundles small, initialise lazily, and use provisioned concurrency or\n  minimum instances where latency matters.\n- Database connections: every instance opens its own, and a burst exhausts\n  Postgres. Use a pooler or an HTTP driver: RDS Proxy, Cloudflare Hyperdrive,\n  Supabase's pooler, Neon's pooled endpoint or serverless driver, PgBouncer\n  in transaction mode (no session state).\n- Workers are V8 isolates, not Node: KV is eventually consistent (a write can\n  take a minute to show elsewhere), D1 is SQLite, R2 is S3-compatible with no\n  egress fees, Durable Objects give single-threaded consistency and sockets.\n- Long work moves to queues and jobs (`backend-jobs`), never a function held\n  open.\n\n## 3. Container platforms\n\n```toml\n# fly.toml\napp = \"acme-api\"\nprimary_region = \"sin\"\nkill_signal = \"SIGTERM\"\nkill_timeout = 30\n\n[deploy]\n  release_command = \"node dist\u002Fmigrate.js\"\n  strategy = \"rolling\"\n\n[http_service]\n  internal_port = 8080\n  force_https = true\n  auto_stop_machines = \"stop\"\n  auto_start_machines = true\n  min_machines_running = 1\n  [http_service.concurrency]\n    type = \"requests\"\n    soft_limit = 200\n    hard_limit = 250\n\n[[http_service.checks]]\n  grace_period = \"10s\"\n  interval = \"15s\"\n  method = \"GET\"\n  path = \"\u002Fhealthz\"\n  timeout = \"2s\"\n\n[[vm]]\n  size = \"shared-cpu-1x\"\n  memory = \"512mb\"\n```\n\n- Fly.io: the defaults are `kill_signal = \"SIGINT\"` and a 5s `kill_timeout`,\n  hence the two lines above. `release_command` runs in a temporary Machine\n  without volumes (5 minutes by default, `release_command_timeout`). A volume\n  belongs to one Machine in one region, is not replicated, and keeps\n  snapshots for 5 days by default; with volumes only rolling and immediate\n  deploys work. `min_machines_running = 0` saves money and costs a cold start.\n- Render (`render.yaml`): `runtime: docker`, `healthCheckPath`,\n  `preDeployCommand` for migrations, `envVars` with `fromDatabase`,\n  `generateValue: true` for generated secrets and `sync: false` for values\n  entered in the dashboard. A disk disables zero-downtime deploys and\n  scaling; the shutdown delay is 30s (`maxShutdownDelaySeconds`, up to 300).\n  Free services sleep after 15 minutes idle.\n- Railway (`railway.json`): Railpack builds by default, `healthcheckPath`,\n  `preDeployCommand`, `overlapSeconds` and `drainingSeconds`; a service with\n  a volume redeploys with a short gap rather than an overlap.\n- Google Cloud Run: concurrency 80 per instance by default (up to 1000),\n  request timeout 300s (up to 3600), 100 instances maximum by default, 10s\n  after `SIGTERM`. With request-based billing the CPU is throttled outside\n  requests, so work after the response stalls: use `--no-cpu-throttling` or\n  a job. `--min-instances=1` removes cold starts;\n  `--set-secrets=DATABASE_URL=database-url:latest` reads Secret Manager.\n- AWS: App Runner stopped taking new customers on 30 April 2026; use ECS\n  Express Mode (a Fargate service, load balancer and autoscaling from one\n  call) or ECS on Fargate. Azure Container Apps scale on KEDA rules, to zero.\n\n## 4. Self-hosted PaaS\n\n- Coolify (4.3), Dokku, CapRover, Kamal: one server or a few, a proxy in\n  front with automatic certificates (Traefik v3 by default in Coolify, Caddy\n  optional), deploys on Git push or webhook. You patch the server, watch its\n  disk and back it up.\n- Coolify builds with Nixpacks, Railpack, a Dockerfile, a Compose file, an\n  image or static files; previews come through its GitHub App; database\n  backups go to S3-compatible storage on a schedule.\n- Coolify's rolling update starts the new container, waits for its health\n  check, then stops the old one: two copies run at once. A process that locks\n  a volume, a SQLite file or a lock file fails in the new copy; switch on\n  \"Consistent container name\" for that app (stop, then start). Rolling is\n  also off with a published host port, a custom container name, Compose\n  deployments and previews.\n- Configure a health check on every Coolify app, or a broken build replaces\n  a working one; its dashboard checks run `curl` or `wget` inside the\n  container (`devops-containers`).\n- Set memory and CPU limits per app: one leaking process otherwise pushes the\n  host into swap and slows every app on it, and a restart that starts the new\n  container first needs headroom for two.\n- Keep \"Make it publicly available\" off for databases; reach them through an\n  SSH tunnel or Tailscale. Back up `\u002Fdata\u002Fcoolify` and the volumes, not only\n  the databases.\n- Dokku is Heroku-like (`git push dokku main`, checks from `app.json`);\n  CapRover runs on Docker Swarm; Kamal 2 deploys containers over SSH with\n  kamal-proxy switching traffic, and `kamal rollback \u003Cversion>`.\n- The server: automatic security updates, a firewall with only 80, 443 and\n  SSH (or SSH through Tailscale), disk alerts at 80%, Docker log rotation\n  (`max-size` and `max-file`, or the `local` log driver; the default\n  `json-file` never rotates), off-site backups (`devops-security`).\n\n## 5. Big clouds\n\n- AWS ECS on Fargate is the default container service there: task\n  definitions, services behind an ALB, rolling deploys with the circuit\n  breaker, no nodes to patch.\n- EKS, GKE or AKS when the organisation already runs Kubernetes or needs its\n  ecosystem; GKE Autopilot and EKS Auto Mode take node management away.\n- Their quiet costs: NAT gateway data processing, traffic between zones, a\n  load balancer per service, idle clusters, log ingestion.\n\n## 6. Managed data\n\n| Need | Defaults | Watch |\n|---|---|---|\n| Postgres | Neon, Supabase, RDS or Aurora, Cloud SQL, Fly Managed Postgres | Same region as the app, point-in-time recovery, connection limits, a pooler for serverless |\n| Redis-compatible | Upstash (per request, HTTP API), managed Valkey (ElastiCache, Memorystore) | Eviction policy; not a primary store |\n| Object storage | S3, Cloudflare R2, GCS, Backblaze B2, Hetzner Object Storage | Egress fees (none on R2), public access blocked by default, lifecycle rules |\n\n- Supabase's direct connection is IPv6 only unless the IPv4 add-on is\n  bought; from IPv4-only hosts (many PaaS and CI runners) use its shared\n  pooler: session mode on 5432, transaction mode on 6543.\n- Neon scales to zero, so the first query after idle waits for a cold start;\n  its branches suit preview environments.\n- Backups: automated daily with point-in-time recovery (7 days at least, 30\n  for important data), a restore tested every quarter, and a periodic\n  `pg_dump` kept with another provider.\n- SQLite in production means one writer on a persistent volume, WAL mode and\n  continuous backup (Litestream).\n\n## 7. Cost and lock-in\n\n- Scale to zero trades money for cold starts; minimum instances trade back.\n- Egress: the big clouds charge per GB leaving (and crossing zones); a CDN in\n  front and R2 for downloads cut it.\n- Per-seat plans grow with the team, not the traffic; free tiers sleep or\n  stop, and are not production.\n- Keep business logic out of platform-specific APIs unless they earn it.\n- Never invent a price: link the pricing page and state the assumptions\n  (requests, GB, hours) behind any estimate.\n- Domains and certificates on each platform: `devops-networking`.\n\n## Check it\n\n- The platform's config validates: `fly config validate`,\n  `npx wrangler deploy --dry-run`, `vercel build`, `docker compose config -q`\n  for Compose apps on Coolify.\n- App and database are in the same region; one query's latency measured from\n  the app, not guessed.\n- The largest upload, longest request and any WebSocket or stream fit the\n  limits table above.\n- Health check configured; one deploy to staging watched from start to\n  healthy; shutdown timing set (`kill_signal` and `kill_timeout` on Fly).\n- A cost estimate written with its assumptions, or marked as not done.\n\n## Avoid\n\nWebSockets or long jobs on serverless functions; a database in a different\nregion from its app; SQLite or uploads on an ephemeral disk; Kubernetes for a\nsingle small service; a free tier in production; Coolify apps with no health\ncheck, no memory limit, or a volume lock under rolling updates; databases\npublished to the internet; Docker logs left to fill the disk; App Runner for\nnew AWS work; edge functions that query a one-region database on every\nrequest; prices stated without a source.\n","# Hosting platforms\n\nThe generated choice is whatever the tutorial used: a WebSocket server on\nserverless functions that cannot hold a socket, a queue worker on a free tier\nthat sleeps after fifteen minutes, the app in one continent and its database\nin another, SQLite on a disk that vanishes on every deploy, Kubernetes for one\nservice run by one person, and an egress bill nobody expected. This is how to\nmatch the app's shape (stateless or stateful, requests or long-running work,\none region or several) to a platform, and the settings each one needs. One\npart of devops; the whole is in the `devops` skill.\n\n## 1. Choosing\n\n| The app | Default | Also good | Not |\n|---|---|---|---|\n| Static site, SPA, docs | Cloudflare (Workers static assets or Pages), Netlify, Vercel | Object storage behind a CDN | A server for static files |\n| SSR framework (Next.js, Nuxt, SvelteKit) | Vercel for Next.js, Netlify, Cloudflare | A container on Fly, Render, Cloud Run, Coolify | |\n| Stateless API or web app in a container | Cloud Run, Fly.io, Render, Railway | ECS Express Mode, Azure Container Apps, Coolify | |\n| WebSockets, long streams, queue workers | Fly.io, Render, Railway, Coolify, ECS on Fargate | Cloudflare Durable Objects; Cloud Run within its 60-minute request limit | Serverless functions |\n| A persistent disk (SQLite, files, an index) | Fly volume, Render disk, Railway volume, a VPS | Move the state to Postgres and object storage | Hosts with ephemeral disks |\n| Spiky, event-driven glue | AWS Lambda, Cloudflare Workers, Vercel Functions | Cloud Run jobs | Idle always-on containers |\n| Many services and teams, compliance | ECS on Fargate, managed Kubernetes (`devops-kubernetes`) | | A self-managed cluster |\n| Small budget, several small apps | A VPS (Hetzner, OVH, DigitalOcean) with Coolify or Kamal | Dokku | Hand-built, unpatched servers |\n\nWeigh, in order: the state the app keeps (disks, sockets, long jobs); where\nits data lives (app and database in the same region: a cross-region query\ncosts 50 to 200ms and more, every time); traffic shape (steady, spiky, idle\nmost of the day); who patches and is on call; cost at rest and at ten times\nthe traffic, including egress and per-seat pricing; data residency and\ncompliance reports; and lock-in (a container, Postgres and the S3 API move in\na day, platform-specific stores and runtimes take a rewrite).\n\n## 2. Frontend and function limits\n\n- Build settings live in the repository (`vercel.json`, `netlify.toml`,\n  `wrangler.jsonc`) with the Node version pinned, not only in a dashboard.\n- Variables per environment (production, preview, development). Anything\n  prefixed `NEXT_PUBLIC_` or `VITE_` is compiled into the bundle and public.\n- Previews for every PR, protected (Vercel Deployment Protection, Cloudflare\n  Access) when the app is not public.\n\n| | Vercel Functions | Cloudflare Workers | AWS Lambda |\n|---|---|---|---|\n| Duration | 300s default; up to 800s on Pro and Enterprise | No wall limit while the client is connected; CPU 10ms on Free, 30s default and 5 min maximum on paid | 15 min |\n| Memory | 2 GB (4 GB on Pro) | 128 MB per isolate | Up to 10,240 MB |\n| Request body | 4.5 MB | 100 MB on Free and Pro zones | 6 MB synchronous (streamed responses up to 200 MB) |\n| WebSockets | Public beta | Yes, through Durable Objects | Through API Gateway WebSocket APIs |\n| Node APIs | Full Node | Partial, with the `nodejs_compat` flag | Full |\n\n- Edge runtimes start in milliseconds near the user, but the database sits in\n  one region, so edge code that queries it pays the round trip on every\n  query. Default to the Node runtime in the database's region; keep edge for\n  redirects, headers, auth checks and cached reads. Vercel runs functions in\n  `iad1` unless told otherwise.\n- Cold starts: close to none for Workers isolates, hundreds of milliseconds\n  to seconds for Lambda with large bundles or a JVM (SnapStart helps). Keep\n  bundles small, initialise lazily, and use provisioned concurrency or\n  minimum instances where latency matters.\n- Database connections: every instance opens its own, and a burst exhausts\n  Postgres. Use a pooler or an HTTP driver: RDS Proxy, Cloudflare Hyperdrive,\n  Supabase's pooler, Neon's pooled endpoint or serverless driver, PgBouncer\n  in transaction mode (no session state).\n- Workers are V8 isolates, not Node: KV is eventually consistent (a write can\n  take a minute to show elsewhere), D1 is SQLite, R2 is S3-compatible with no\n  egress fees, Durable Objects give single-threaded consistency and sockets.\n- Long work moves to queues and jobs (`backend-jobs`), never a function held\n  open.\n\n## 3. Container platforms\n\n```toml\n# fly.toml\napp = \"acme-api\"\nprimary_region = \"sin\"\nkill_signal = \"SIGTERM\"\nkill_timeout = 30\n\n[deploy]\n  release_command = \"node dist\u002Fmigrate.js\"\n  strategy = \"rolling\"\n\n[http_service]\n  internal_port = 8080\n  force_https = true\n  auto_stop_machines = \"stop\"\n  auto_start_machines = true\n  min_machines_running = 1\n  [http_service.concurrency]\n    type = \"requests\"\n    soft_limit = 200\n    hard_limit = 250\n\n[[http_service.checks]]\n  grace_period = \"10s\"\n  interval = \"15s\"\n  method = \"GET\"\n  path = \"\u002Fhealthz\"\n  timeout = \"2s\"\n\n[[vm]]\n  size = \"shared-cpu-1x\"\n  memory = \"512mb\"\n```\n\n- Fly.io: the defaults are `kill_signal = \"SIGINT\"` and a 5s `kill_timeout`,\n  hence the two lines above. `release_command` runs in a temporary Machine\n  without volumes (5 minutes by default, `release_command_timeout`). A volume\n  belongs to one Machine in one region, is not replicated, and keeps\n  snapshots for 5 days by default; with volumes only rolling and immediate\n  deploys work. `min_machines_running = 0` saves money and costs a cold start.\n- Render (`render.yaml`): `runtime: docker`, `healthCheckPath`,\n  `preDeployCommand` for migrations, `envVars` with `fromDatabase`,\n  `generateValue: true` for generated secrets and `sync: false` for values\n  entered in the dashboard. A disk disables zero-downtime deploys and\n  scaling; the shutdown delay is 30s (`maxShutdownDelaySeconds`, up to 300).\n  Free services sleep after 15 minutes idle.\n- Railway (`railway.json`): Railpack builds by default, `healthcheckPath`,\n  `preDeployCommand`, `overlapSeconds` and `drainingSeconds`; a service with\n  a volume redeploys with a short gap rather than an overlap.\n- Google Cloud Run: concurrency 80 per instance by default (up to 1000),\n  request timeout 300s (up to 3600), 100 instances maximum by default, 10s\n  after `SIGTERM`. With request-based billing the CPU is throttled outside\n  requests, so work after the response stalls: use `--no-cpu-throttling` or\n  a job. `--min-instances=1` removes cold starts;\n  `--set-secrets=DATABASE_URL=database-url:latest` reads Secret Manager.\n- AWS: App Runner stopped taking new customers on 30 April 2026; use ECS\n  Express Mode (a Fargate service, load balancer and autoscaling from one\n  call) or ECS on Fargate. Azure Container Apps scale on KEDA rules, to zero.\n\n## 4. Self-hosted PaaS\n\n- Coolify (4.3), Dokku, CapRover, Kamal: one server or a few, a proxy in\n  front with automatic certificates (Traefik v3 by default in Coolify, Caddy\n  optional), deploys on Git push or webhook. You patch the server, watch its\n  disk and back it up.\n- Coolify builds with Nixpacks, Railpack, a Dockerfile, a Compose file, an\n  image or static files; previews come through its GitHub App; database\n  backups go to S3-compatible storage on a schedule.\n- Coolify's rolling update starts the new container, waits for its health\n  check, then stops the old one: two copies run at once. A process that locks\n  a volume, a SQLite file or a lock file fails in the new copy; switch on\n  \"Consistent container name\" for that app (stop, then start). Rolling is\n  also off with a published host port, a custom container name, Compose\n  deployments and previews.\n- Configure a health check on every Coolify app, or a broken build replaces\n  a working one; its dashboard checks run `curl` or `wget` inside the\n  container (`devops-containers`).\n- Set memory and CPU limits per app: one leaking process otherwise pushes the\n  host into swap and slows every app on it, and a restart that starts the new\n  container first needs headroom for two.\n- Keep \"Make it publicly available\" off for databases; reach them through an\n  SSH tunnel or Tailscale. Back up `\u002Fdata\u002Fcoolify` and the volumes, not only\n  the databases.\n- Dokku is Heroku-like (`git push dokku main`, checks from `app.json`);\n  CapRover runs on Docker Swarm; Kamal 2 deploys containers over SSH with\n  kamal-proxy switching traffic, and `kamal rollback \u003Cversion>`.\n- The server: automatic security updates, a firewall with only 80, 443 and\n  SSH (or SSH through Tailscale), disk alerts at 80%, Docker log rotation\n  (`max-size` and `max-file`, or the `local` log driver; the default\n  `json-file` never rotates), off-site backups (`devops-security`).\n\n## 5. Big clouds\n\n- AWS ECS on Fargate is the default container service there: task\n  definitions, services behind an ALB, rolling deploys with the circuit\n  breaker, no nodes to patch.\n- EKS, GKE or AKS when the organisation already runs Kubernetes or needs its\n  ecosystem; GKE Autopilot and EKS Auto Mode take node management away.\n- Their quiet costs: NAT gateway data processing, traffic between zones, a\n  load balancer per service, idle clusters, log ingestion.\n\n## 6. Managed data\n\n| Need | Defaults | Watch |\n|---|---|---|\n| Postgres | Neon, Supabase, RDS or Aurora, Cloud SQL, Fly Managed Postgres | Same region as the app, point-in-time recovery, connection limits, a pooler for serverless |\n| Redis-compatible | Upstash (per request, HTTP API), managed Valkey (ElastiCache, Memorystore) | Eviction policy; not a primary store |\n| Object storage | S3, Cloudflare R2, GCS, Backblaze B2, Hetzner Object Storage | Egress fees (none on R2), public access blocked by default, lifecycle rules |\n\n- Supabase's direct connection is IPv6 only unless the IPv4 add-on is\n  bought; from IPv4-only hosts (many PaaS and CI runners) use its shared\n  pooler: session mode on 5432, transaction mode on 6543.\n- Neon scales to zero, so the first query after idle waits for a cold start;\n  its branches suit preview environments.\n- Backups: automated daily with point-in-time recovery (7 days at least, 30\n  for important data), a restore tested every quarter, and a periodic\n  `pg_dump` kept with another provider.\n- SQLite in production means one writer on a persistent volume, WAL mode and\n  continuous backup (Litestream).\n\n## 7. Cost and lock-in\n\n- Scale to zero trades money for cold starts; minimum instances trade back.\n- Egress: the big clouds charge per GB leaving (and crossing zones); a CDN in\n  front and R2 for downloads cut it.\n- Per-seat plans grow with the team, not the traffic; free tiers sleep or\n  stop, and are not production.\n- Keep business logic out of platform-specific APIs unless they earn it.\n- Never invent a price: link the pricing page and state the assumptions\n  (requests, GB, hours) behind any estimate.\n- Domains and certificates on each platform: `devops-networking`.\n\n## Check it\n\n- The platform's config validates: `fly config validate`,\n  `npx wrangler deploy --dry-run`, `vercel build`, `docker compose config -q`\n  for Compose apps on Coolify.\n- App and database are in the same region; one query's latency measured from\n  the app, not guessed.\n- The largest upload, longest request and any WebSocket or stream fit the\n  limits table above.\n- Health check configured; one deploy to staging watched from start to\n  healthy; shutdown timing set (`kill_signal` and `kill_timeout` on Fly).\n- A cost estimate written with its assumptions, or marked as not done.\n\n## Avoid\n\nWebSockets or long jobs on serverless functions; a database in a different\nregion from its app; SQLite or uploads on an ephemeral disk; Kubernetes for a\nsingle small service; a free tier in production; Coolify apps with no health\ncheck, no memory limit, or a volume lock under rolling updates; databases\npublished to the internet; Docker logs left to fill the disk; App Runner for\nnew AWS work; edge functions that query a one-region database on every\nrequest; prices stated without a source.\n",{"name":5,"description":7},"main","38293fe1b096e6bf3646c7344c38786ed688f464","crates\u002Fenowx-core\u002Fskills\u002Fdevops-platforms",21,"https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli","https:\u002F\u002Fenowx.ai","https:\u002F\u002Fgithub.com\u002Fenowdev","Pretending to be a Developer","2026-10-06 02:05:35",{"source":8,"skillName":5,"commands":55,"prompt":65,"zipAvailable":66},[56,59,62],{"tool":57,"command":58},"npx","npx skills add enowdev\u002Fenowxcli --skill devops-platforms",{"tool":60,"command":61},"bunx","bunx skills add enowdev\u002Fenowxcli --skill devops-platforms",{"tool":63,"command":64},"pnpm","pnpm dlx skills add enowdev\u002Fenowxcli --skill devops-platforms","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fdevops-platforms\u002FSKILL.md",true,[],[69,83,108,124,151,173],{"skillNo":70,"name":71,"nameZh":6,"description":72,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":73,"categories":74,"keywords":78,"publishedAt":40},"01M6D2HQYSQD9N7MTNDT4A7CBM","demo-skill","Project-scope demo skill for tests.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fworkspace\u002F.agents\u002Fskills\u002Fdemo-skill\u002FSKILL.md",[75],{"categoryNo":76,"categoryName":77,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[79,80,81,82,29],"demo skill","demo","tests","project",{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":87,"categories":88,"keywords":97,"publishedAt":40},"01M6D2HM0GCPM0TM2HPG9HHR2R","writing","Writing words people read: the specific thing instead of claims, words to drop, sentences, interface copy (buttons, labels, errors, empty states, confirmations), page copy, notifications and emails, alt text and link text, numbers and dates, words that translate well, documentation and voice. Read before writing a page's copy, an interface's text or a document.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fwriting\u002FSKILL.md",[89,92],{"categoryNo":90,"categoryName":91,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":93,"categoryName":94,"taxonomyType":95,"taxonomyTypeDesc":96},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[85,98,99,100,101,102,29,103,104,105,106,107],"text","emails","empty","drop","document","page","voice","notifications","documentation","translate",{"skillNo":109,"name":110,"nameZh":6,"description":111,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":112,"categories":113,"keywords":117,"publishedAt":40},"01M6D2HG07YS49NM196Q0R3AZ8","ui","Designing or restyling an interface: direction, layout, type, colour, icons, components, states, responsive behaviour. Read before building a page, a screen or a set of components.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui\u002FSKILL.md",[114],{"categoryNo":115,"categoryName":116,"taxonomyType":95,"taxonomyTypeDesc":96},"01JBSEEDCAT000000000000032","设计师",[110,118,119,120,121,103,122,29,123],"icons","components","SET","responsive","layout","before building",{"skillNo":125,"name":126,"nameZh":6,"description":127,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":128,"categories":129,"keywords":136,"publishedAt":40},"01M6D2HB59HZHWG1RYZDV4SJ91","ui-themes","Light and dark themes, and colour that holds in both: tokens with a value per theme, and what each kind of content needs to stay visible (icons, SVG drawings and line art, logos, photos, screenshots, charts, code, maps, borders, shadows, focus, form controls), switching without a flash, and checking both. Read before building a second theme or a theme toggle, and before any drawing, logo or chart on a page that has two themes.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui-themes\u002FSKILL.md",[130,133],{"categoryNo":131,"categoryName":132,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":134,"categoryName":135,"taxonomyType":95,"taxonomyTypeDesc":96},"01JBSEEDCAT000000000000030","开发工程师",[110,137,138,139,140,141,142,143,144,29,123,145,103,146,147,148,118,149,150],"ui themes","switching","photos","tokens","drawing","focus","maps","Art","flash","code","Charts","content","screenshots","logo",{"skillNo":152,"name":153,"nameZh":6,"description":154,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":155,"categories":156,"keywords":160,"publishedAt":40},"01M6D2H5R5KRAE524C8QX0T7Q0","ui-structure","Structure before styling: the blueprint written before any interface code (the screen's job, the regions its kind of page needs, their order and why, the layout skeleton in numbers, the components and their states), the anatomy and order of a homepage, a dashboard, a list, a detail page, settings, a form, sign-in, pricing, docs, an article and a checkout, and how to turn the blueprint into code (tokens, layout primitives, components, sections, page). Read first, before building or rebuilding any page or screen.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui-structure\u002FSKILL.md",[157,158,159],{"categoryNo":90,"categoryName":91,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":134,"categoryName":135,"taxonomyType":95,"taxonomyTypeDesc":96},{"categoryNo":93,"categoryName":94,"taxonomyType":95,"taxonomyTypeDesc":96},[161,110,162,119,163,164,146,165,166,167,122,140,168,169,170,29,123,103,171,172],"structure","ui structure","pricing","dashboard","Blueprint","article","anatomy","styling","primitives","list","why","how",{"skillNo":174,"name":175,"nameZh":6,"description":176,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":177,"categories":178,"keywords":184,"publishedAt":40},"01M6D2H0ZZBJG77MBGPZHA6MWD","ui-stack-vue","Building interfaces in Vue 3 and Nuxt: project layout, script setup with typed defineProps, defineEmits and defineModel, attribute fallthrough, slots and scoped slots, template refs, ref, reactive and computed, watch versus watchEffect, composables and VueUse, provide and inject, Pinia, keyed v-for, transitions, Nuxt 4 (app directory, pages, layouts, useFetch and useAsyncData keys, $fetch in handlers, server routes, runtime config, useSeoMeta, NuxtImg, middleware), VeeValidate forms, Reka UI and Nuxt UI, testing, vue-tsc, and the traps. Read when the project uses Vue or Nuxt.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui-stack-vue\u002FSKILL.md",[179,182,183],{"categoryNo":180,"categoryName":181,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":115,"categoryName":116,"taxonomyType":95,"taxonomyTypeDesc":96},[110,185,186,187,188,189,190,191,122,82,192,193,29,194,195,196,197,198,199,200],"vue","stack","ui stack vue","forms","pages","watch","runtime","transitions","fetch","pinia","nuxt","template","server","config","directory","testing"]