# The cutover day checklist: moving traffic to Cloud Run with the old app as the way back

> The day traffic moves to Cloud Run, step by step from a week before to a week after: the DNS TTL, freeze, copy, compare and switch, checks from outside, the way back, and the overlap's cost.

Published 2026-10-12 · Updated 2026-10-13 · [By Exodus team](https://exodus.elim.io/about) · Operations
<https://exodus.elim.io/blog/the-cutover-day-checklist>

Cutover day for a move to Cloud Run runs in five moments. A week before, the new app serves on its run.app address with alerts and a written way back. A day before, the DNS TTL drops to 300 seconds. In the hour, writes freeze, the data is copied and compared, and the record switches. Then a week of watching, with the old app kept as the rollback.

## In short

- Lower the DNS TTL to 300 seconds a day before: the new TTL applies only after the old one expires, an hour later for 3600 and a day later for 86400.
- A Cloud Run domain mapping issues its certificate only after DNS points at it, in about 10 minutes when the record existed first and up to 24 hours by Google's page; a load balancer with DNS authorization or Firebase Hosting's Advanced Setup issues it ahead.
- Stripe retries a refused webhook for up to 3 days in live mode, so events refused by the old app's maintenance page reach the new app later.
- A warm minimum instance of 1 vCPU and 512 MiB costs $0.32 a day, $2.27 a week; the old platform keeps billing for the week it stays as the way back.

Commands were checked against `gcloud 587.0.0 --help`, and the read-only ones were run on October 12, 2026.

## The rule: the old app is the way back

The cutover is the hour when the address your users know stops pointing at the old host and starts pointing at Cloud Run. Everything before it can be redone; the cutover touches real users, payments and data. This checklist works for an app leaving Heroku, Render, Railway, Fly, a VPS or anything else, and keeps one rule: the old app stays able to take traffic back until the new one has served real users for a week.

Until then the rollback is to point DNS back. Writes made on the new app after the switch would have to be copied back by hand, so keep the time between the switch and the decision short and know which tables take writes.

The data half, with every flag of `pg_dump` and `pg_restore` and the compare query, is in [moving a Postgres database without losing data](https://exodus.elim.io/blog/moving-a-postgres-database-without-losing-data). This guide is the rest of the day around it.

![A timeline of the cutover in five rows: a week before, the new app is live on run.app with alerts and a written way back; a day before, the DNS TTL is lowered to 300 seconds; in the hour, writes are frozen, data copied and compared, and the domain switched; on the first day, errors and latency are watched with the old app as the way back; a week after, the old app is stopped and then deleted](https://exodus.elim.io/media/v2026-09-16/t/exodus/assets/image-d008f606ee3b82e1e6f676b8fca5899da6d08a0427ef84725cf79a9b0e7b9fb1-680x470-svg/bytes "The cutover as five moments. Only the highlighted hour touches users; everything else is preparation or watching.")

## A week before

### The new app serves real requests on run.app

Every Cloud Run service gets an HTTPS address ending in `run.app` when it is created, and keeps it until you turn it off with `--no-default-url`. Deploy the new app there from CI, [without a JSON key](https://exodus.elim.io/blog/deploying-from-github-without-keys), with [its secrets in Secret Manager](https://exodus.elim.io/blog/secrets-on-cloud-run). Point it at a rehearsal copy of the data and walk every path a user takes: sign up, sign in, the main pages, anything that writes, uploads or sends an email.

Two settings matter. By default Cloud Run allows up to 100 instances per revision, and a small Cloud SQL instance accepts far fewer connections than that many instances would open, so set a maximum your database can serve, as [connection pooling on Cloud Run](https://exodus.elim.io/blog/connection-pooling-on-cloud-run) works out. And the first requests after the switch may each start a new instance, so for the day keep one warm:

```shell
gcloud run services update SERVICE --region=REGION --min-instances=1 --max-instances=10
```

Set up the three alerts from [logs, metrics and alerts for a Cloud Run app](https://exodus.elim.io/blog/logs-metrics-and-alerts-for-a-cloud-run-app) too (uptime, 5xx, error logs), and test that each reaches you.

### List everything outside that knows the old app

This is the step people skip. Write down every place that holds an address, a secret or an IP of the old app:

- **Webhooks** from a payment provider, a Git host, a mail provider. A webhook URL on your own domain follows DNS and needs no change. One on the platform's address (`*.herokuapp.com`, `*.onrender.com`, `*.up.railway.app`, `*.fly.dev`) must be changed. Copy the signing secret too: Stripe gives each endpoint its own secret starting with `whsec_`, and the new app must verify with the same one.
- **OAuth sign-in.** Google requires the `redirect_uri` to match one of the client's authorized redirect URIs exactly, or sign-in fails with `redirect_uri_mismatch`. If you also move from a platform address to your own domain, add the new URI now, while both work.
- **IP allow lists.** A partner's API or a firewall may accept only your old server's IP. Cloud Run has no fixed outbound IP by default; one takes VPC egress through a Cloud NAT gateway with a reserved static address. Set it up and send the new IP now.
- **Timers and workers** on the old platform and their counterparts here (see [cron and timers with Cloud Scheduler](https://exodus.elim.io/blog/cron-and-timers-with-cloud-scheduler) and [background workers with Cloud Tasks](https://exodus.elim.io/blog/background-workers-with-cloud-tasks)). Create the Cloud Scheduler jobs now and pause them, so that on the day you resume them:

```shell
gcloud scheduler jobs pause JOB --location=REGION
```

- **Files** on the old platform's disk or storage, copied to a bucket now and again during the freeze, as [files and uploads with Cloud Storage](https://exodus.elim.io/blog/files-and-uploads-with-cloud-storage) shows.

### Choose the front and its certificate path

[Custom domains and HTTPS on Cloud Run](https://exodus.elim.io/blog/custom-domains-and-https-on-cloud-run) compares the three fronts: Cloud Run domain mapping, a load balancer and Firebase Hosting. For the cutover one question matters: can the certificate be issued before the switch?

- With a **load balancer and Certificate Manager's DNS authorization**, or **Firebase Hosting's Advanced Setup**, yes. You prove control of the domain with a separate DNS record, the certificate is issued while the old app still serves users, and the switch is one record change. Google's migration page says a certificate authorized by the load balancer itself is not suitable for a move with no downtime "because you can't issue them in advance". You can then test the new front under the real name before anyone uses it, by giving curl the address instead of DNS:

```shell
curl -sI --resolve app.example.com:443:203.0.113.10 https://app.example.com/
```

- With **Cloud Run domain mapping**, no: the certificate is issued once the name points at it. The custom domains guide measured about 10 minutes when the record existed first; Google's page allows up to 24 hours. Plan for HTTPS errors in those minutes, or pick a front that issues ahead.

### Write the way back down

Write the rollback as commands now, while you are calm. Usually it is three steps: point the DNS record back at the old host, take the old app out of maintenance mode, undo the database freeze. Check whether the old host's certificate needs DNS to point at it. If it does, your way back carries its own HTTPS gap.

Exodus team: when we moved two public names between hosts, the fast way back kept the names on the new host and passed their traffic to the old app behind it, so no certificate changed hands: one config deploy, of the kind that took 17 seconds at the switch. Pointing DNS back would have needed a fresh certificate and up to an hour of HTTPS errors.

## A day before

### Lower the TTL

Google's Cloud DNS documentation describes how a change spreads: first to the authoritative servers, then to resolvers "when their cache of the records expires", and the TTL in seconds sets how long they cache. For a change that needs a narrow window it advises lowering the TTL beforehand, with a catch: "the new shorter TTL value is applied after the previous TTL value expires". A record at 3600 lowered to 300 takes effect for everyone an hour later; one at 86400, a day later. Hence a day before.

Look up the current TTL (the checks below show how) and set it to 300 seconds. Google's page also says some resolvers ignore TTLs, so a few users may reach the old app for a while whatever you do. So the old app must keep running and refuse writes, not accept them.

![A chart of how long a resolver may keep the old DNS answer after the record changes: up to 60 minutes with a TTL of 3600 left as it was, up to 5 minutes with a TTL lowered to 300 a day before, and up to 30 minutes of 'no such name' for a new name that was looked up before it existed](https://exodus.elim.io/media/v2026-09-16/t/exodus/assets/image-045e33ea5fb8cd19703203faf1b3e0649f01906b14e8f10ab950c0ef4245c9f5-680x300-svg/bytes "How long users can still land on the old answer after the change. Lowering the TTL a day before shrinks the first bar to the second; the third is why a new record is made before anyone looks it up.")

There is a second cache, for answers that say a name does not exist. RFC 2308 sets its length from the zone's SOA record: the smaller of its last field and its own TTL. Ours gives 1800 seconds, so a resolver that asked for a new name a minute before it was created may answer "no such name" for 30 minutes. Google adds that many resolvers, Windows and the Java runtime among them, cache negative answers for up to 15 minutes. So create new records, such as a certificate's TXT record, well before anything looks them up.

### Rehearse the copy and pick the hour

Run the data rehearsal once more and write down its time. That, plus a few minutes for the compare, is the length of the freeze. If it is longer than users can accept, the Postgres guide covers Database Migration Service, which shortens the freeze to the last changes.

Then pick the hour from your current platform's metrics, or from Cloud Run's `request_count` by hour if the new app has served test traffic.

![A line chart of requests by hour of day, UTC, for 8 Cloud Run services over eight days in October 2026: the busiest hour is 09:00 with 3,959 requests, the quietest is 00:00 with 134](https://exodus.elim.io/media/v2026-09-16/t/exodus/assets/image-18f66c452fbf0f8b2567bc9b87721dab970c5e27f5428c6db64d1b2fef684a7b-680x340-svg/bytes "Exodus team: 20,081 requests to 8 services, summed by hour of day, October 4 to 12, 2026. The quietest hour had 134, the busiest 3,959, about 30 times more.")

A freeze in our quietest hour would touch 30 times fewer people than in the busiest. The quietest hour is often the middle of the night, though, and someone must be awake to watch; a quiet working afternoon with the whole team there is often better. Tell users the time and the length of the window.

## The hour

Do these in order, with one person reading the list and one typing.

1. **Warm the new app.** Check that one minimum instance is set and that the health route answers on `run.app`.
1. **Put the old app in maintenance mode.** On Heroku it serves a static page to every visitor and logs error H80, but Heroku's page says Scheduler jobs can still run and worker dynos keep running, so stop them too, for example with `heroku ps:scale worker=0`. Elsewhere, use the platform's maintenance page or scale the web process to zero.
1. **Freeze writes in the database** as well, because a worker or timer you forgot will otherwise write after the copy. The Postgres guide does this with `default_transaction_read_only`.
1. **Copy the data and the files again and compare.** This time counts, checksums and sequence values must match line for line.
1. **Point the DNS record at the new front.** If your DNS provider can proxy traffic, keep the record DNS-only.
1. **Check from outside** (next section) until public resolvers return the new target and HTTPS on your domain reaches the new app.
1. **Resume the timers** on the new side, after checking the old side's are stopped:

```shell
gcloud scheduler jobs resume JOB --location=REGION
```

1. **Update what does not follow DNS:** webhook URLs on the platform address, OAuth redirect URIs, partners' allow lists, if any are left from the week before.
1. **Walk the main paths** on the real domain: sign in, the page that sells, a write, an upload, a webhook.
1. **Leave the old app in maintenance and its database read-only.** Delete nothing.

Webhooks sent during the switch are less of a worry than they look, if the old app refused them. Stripe retries a failed delivery for up to three days in live mode ([Stripe webhooks on Cloud Run](https://exodus.elim.io/blog/stripe-webhooks-on-cloud-run) has the details), so events refused by the maintenance page reach the new app later, as long as the endpoint URL is on your domain. An old app that accepts a webhook and writes it into a database you will throw away loses the event. That is why the freeze goes in the database too.

## Checking from outside

Your own machine is the worst place to check DNS from: it has its own cache, perhaps a VPN, a corporate resolver or an old line in `/etc/hosts`. Ask public resolvers and your zone's name servers directly:

```shell
dig +noall +answer app.example.com @8.8.8.8
dig +noall +answer app.example.com @1.1.1.1
dig +noall +answer app.example.com @NAMESERVER_OF_YOUR_ZONE
```

If `dig` returns an address that makes no sense, something between you and the resolver answered. Google Public DNS also answers over HTTPS, with JSON, which nothing on port 53 can intercept:

```shell
curl -s 'https://dns.google/resolve?name=app.example.com&type=A' \
  | jq -r '.Answer[] | "\(.name) \(.TTL) \(.data)"'
```

![Terminal output of the checks against one of our names, masked as app.example.com: plain dig returns 198.18.2.251, an address from a VPN on the machine; Google's DNS over HTTPS returns a CNAME to ghs.googlehosted.com with a TTL of 300; a lookup of a name that does not exist shows the zone's SOA with 1800 as its last field; a HEAD request over HTTPS answers HTTP/2 200](https://exodus.elim.io/media/v2026-09-16/t/exodus/assets/image-571391c7375fd1f7355f604142c15ab506ecb046884f707433a043e80c2c6dde-680x312-svg/bytes "Exodus team: the checks run on October 12, 2026, names masked. Plain dig was answered by a VPN, not by Google; DNS over HTTPS showed the real record and its TTL.")

Exodus team: when we switched two names between hosts on October 11, Google's and Cloudflare's DNS over HTTPS returned the new target 6 seconds after the record changed, because the TTL had been 300 for weeks.

Then check what answers. `curl -sI https://app.example.com/` should print a status line, but the old app in maintenance answers too, so check something only the new app sends: a header, or a version on its health route.

## The first day

Watch the 5xx alert, latency and the error logs; the logs guide has the 5xx query by revision. Watch the old app's logs too: anything still reaching it is a resolver with an old answer, a webhook with an old URL or a client with a hard-coded address.

If the new code is at fault, not the switch, [roll back to the previous revision](https://exodus.elim.io/blog/revisions-traffic-splitting-and-rollbacks):

```shell
gcloud run services update-traffic SERVICE --region=REGION --to-revisions=PREVIOUS_REVISION=100
```

That is not a rollback of the cutover: users stay on Cloud Run and the new database, with older code. A rollback of the cutover is the plan from a week before: DNS back, the old app out of maintenance, the old database writable. Decide early which one a problem needs, because the longer the new app takes writes, the more you would copy back by hand.

## A week after

When the new app has served a week of real traffic without a reason to go back:

1. **Stop the old app**, scaling its web and worker processes to zero, but keep it for now.
1. **Take a final backup of the old database** somewhere you control, then delete the old database and the old app.
1. **Raise the TTL** back to its old value, as Google's page suggests, to reduce load on resolvers.
1. **Set min instances back to 0** if the app does not need a warm instance.
1. **Remove what only the old app needed**: webhook entries, OAuth redirect URIs and allow-list entries for its address and IP. Rotate the secrets that sat in the old platform's dashboard, because it still holds their values.
1. **Read the first bill**, as [reading your first Google Cloud bill](https://exodus.elim.io/blog/reading-your-first-google-cloud-bill) explains, and check that a [budget alert](https://exodus.elim.io/blog/budget-alerts-and-the-billing-export) exists.

## What it costs

On Google's side the day costs little; the overlap costs a week of the old platform's bill.

- **A warm instance.** At list prices of October 12, 2026 in europe-west1, an idle minimum instance is billed $0.0000025 per vCPU-second and $0.0000025 per GiB-second. One with 1 vCPU and 512 MiB, idle all day, is 86,400 × ($0.0000025 + 0.5 × $0.0000025) = $0.32 a day, $2.27 a week, before the free tier. Idle instances that are not minimum instances are not charged.
- **The old platform** bills until you stop it; Heroku's page says dynos keep accruing billing hours in maintenance mode. A week of overlap is about a quarter of a month of the old bill, the price of the way back.
- **A fixed outbound IP**, if partners need one, is a Cloud NAT gateway and a reserved address: an ongoing cost to price before the day.

## What breaks

- **Users still see the old app hours later.** The TTL was lowered too late, or a resolver ignores it. Keep the old app refusing writes until its logs go quiet.
- **A new name answers "no such name" for half an hour.** It was looked up before the record existed. Make records early.
- **HTTPS fails right after the switch.** The certificate is issued only once DNS points at the front. Wait, or use a front that issues ahead.
- **Sign-in fails.** The error is `redirect_uri_mismatch`: the OAuth client lacks the exact new redirect URI.
- **The first request answers 403.** The service is private: see [IAM for a Cloud Run app](https://exodus.elim.io/blog/iam-for-a-cloud-run-app) for the public setting.
- **Webhooks fail signature checks.** The new app has a different signing secret from the endpoint's.
- **A partner's API refuses calls.** It allow-lists the old IP; use a static outbound IP through Cloud NAT.
- **Customers get two emails from a nightly job.** The timer runs on both platforms. Pause one side before resuming the other.
- **The first requests are slow, or the database refuses connections.** No warm instance, or more instances than the database can serve.

## The checklist

A week before:

1. New app on `run.app`, deployed from CI, secrets in Secret Manager, main paths walked against a copy.
1. Max instances matched to the database; min instances 1 for the day; three alerts tested.
1. Webhooks, OAuth redirect URIs, allow lists, timers, workers and files listed; Cloud Scheduler jobs created and paused.
1. The front chosen, its certificate path known, tested under the real name with `curl --resolve` where possible.
1. The way back written as commands.

A day before:

1. TTL lowered to 300 seconds; new records created.
1. Copy rehearsed and timed; the hour picked; users told.

The hour:

1. Old app in maintenance, workers and timers stopped, writes frozen in the database.
1. Data and files copied again; counts, checksums and sequences identical.
1. DNS switched and checked over HTTPS from public resolvers; the new app answering under the real name.
1. Timers resumed here; webhooks, OAuth and allow lists updated; main paths walked.

After:

1. 5xx, latency and logs watched on both apps for a day.
1. After a week: old app stopped, backed up, deleted; old secrets rotated; TTL raised; min instances 0; first bill read.

## Where Exodus comes in

When Exodus audits a repository, the cutover is the last phase of the plan it writes: a data copy with a compare, and "Switch the domain and stop" the old platform, in a quiet hour, keeping it stopped, not deleted, for a week. Three of the audit's questions exist for this day: which domains point at the app, whether it can be down for a few minutes, and which outside services it calls.

![Terminal output of the exodus CLI on a sample Rails app that runs on Heroku: the plan has nine tasks, the last two in the Cut over phase, a data copy with a compare and a switch of the domain that keeps Heroku stopped, not deleted, for a week; the report's questions ask which domains point at the app, whether it can be down a few minutes, and which outside services it calls](https://exodus.elim.io/media/v2026-09-16/t/exodus/assets/image-a8c291010282c642ead28da82ab60bb0ba373954f230004d71fd311a6f392ba6-680x332-svg/bytes "The exodus CLI 0.1.1 on a sample Rails app on Heroku. The plan ends with the two cutover tasks, and the report asks the three questions this day depends on.")

## FAQ

### How far ahead should I lower the DNS TTL before a migration?

A day before, to 300 seconds. Google's Cloud DNS page says a new, shorter TTL applies only after the previous one expires, so a record at 3600 takes an hour to pick it up and one at 86400 a day. Some resolvers ignore TTLs, so the old app keeps running and refuses writes.

### Why does a new DNS record answer "no such name" after I create it?

A resolver cached the negative answer from before the record existed. RFC 2308 sets that cache from the zone's SOA record; ours gives 1800 seconds, 30 minutes. Many resolvers, Windows and the Java runtime among them, cache negative answers for up to 15 minutes. Create new records well before anything looks them up.

### How do I roll back a move to Cloud Run?

It depends on what failed. If the new code is at fault, send traffic back to the previous revision; users stay on Cloud Run. If the move itself is at fault, point DNS back, take the old app out of maintenance and make the old database writable. Writes made on the new app since the switch are copied back by hand.

### Will webhooks be lost during the cutover?

Not if the old app refuses them and the endpoint URL is on your own domain. Stripe retries a failed delivery for up to three days in live mode, so events refused by the maintenance page reach the new app later. An old app that accepts a webhook and writes it into a database you will throw away loses the event.

### How do I check DNS propagation after the switch?

Ask public resolvers and your zone's name servers directly, not your own machine, which may have a cache, a VPN or an old hosts entry. Google Public DNS also answers over HTTPS with JSON, which nothing on port 53 can intercept. Then request something only the new app sends, such as a header or a version on its health route.

## Sources

1. [Cloud DNS overview, Google (changes propagate in two parts, to the authoritative servers and then to resolvers when their cache expires; the TTL controls the resolver's cache, 86400 s is 24 hours; some resolvers ignore the TTL; lower the TTL before a change that needs a narrow window, the new TTL applies after the previous one expires, raise it again afterwards; many stub and recursive resolvers cache negative answers for up to 15 minutes; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/dns/docs/overview)
2. [RFC 2308, Negative Caching of DNS Queries, IETF (the TTL of a negative answer is the minimum of the SOA's MINIMUM field and the SOA's own TTL; read Oct 12, 2026)](https://www.rfc-editor.org/rfc/rfc2308.html)
3. [Google Public DNS JSON API, Google (https://dns.google/resolve with name and type, only name required, answers as JSON over HTTPS; read Oct 12, 2026)](https://developers.google.com/speed/public-dns/docs/doh/json)
4. [curl man page, curl project (--resolve host:port:addr sends a request for a name to an address you choose, without DNS; read Oct 12, 2026)](https://curl.se/docs/manpage.html)
5. [Map custom domains, Cloud Run, Google (a mapping's certificate usually takes about 15 minutes and can take up to 24 hours; read Oct 12, 2026)](https://docs.cloud.google.com/run/docs/mapping-custom-domains)
6. [Migrate load balancer certificates to Certificate Manager, Google (Google-managed certificates with load balancer authorization are not suitable for a migration with no downtime because they cannot be issued in advance; test the new configuration before the migration; updated Jun 29, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/certificate-manager/docs/migrate-lb)
7. [Connect a custom domain, Firebase Hosting (Advanced Setup establishes a certificate and ownership so Hosting can serve the domain before traffic is directed to it, for a zero-downtime migration from another provider; read Oct 12, 2026)](https://firebase.google.com/docs/hosting/custom-domain)
8. [Set minimum instances for services, Cloud Run, Google (min instances keep that many instances running even when they serve no requests; updated Oct 7, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/run/docs/configuring/min-instances)
9. [Set maximum instances for services, Cloud Run, Google (by default Cloud Run sets 100 instances for each revision; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/run/docs/configuring/max-instances)
10. [Cloud Run pricing, Google (europe-west1 is a Tier 1 region; idle time of a min instance $0.0000025 per vCPU-second and $0.0000025 per GiB-second; idle instances that are not minimum instances are not charged; list prices read Oct 12, 2026)](https://cloud.google.com/run/pricing)
11. [Default URL for Cloud Run, Google (every service gets a run.app URL; --no-default-url turns it off, --default-url restores it; updated Sep 30, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/run/docs/configuring/instances/default-url)
12. [Static outbound IP address, Cloud Run, Google (a fixed outbound address needs VPC egress through a VPC network with a Cloud NAT gateway that holds a reserved static IP; updated Oct 7, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/run/docs/configuring/static-outbound-ip)
13. [Manage cron jobs, Cloud Scheduler, Google (gcloud scheduler jobs pause and resume; a paused job stays paused until it is resumed and can be edited meanwhile; updated Oct 9, 2026, read Oct 12, 2026)](https://docs.cloud.google.com/scheduler/docs/creating)
14. [Receive Stripe events in your webhook endpoint, Stripe (each endpoint has its own signing secret starting with whsec_; in live mode Stripe retries delivery for up to three days with exponential back off; a rolled secret can stay valid for up to 24 hours; read Oct 12, 2026)](https://docs.stripe.com/webhooks)
15. [Using OAuth 2.0 for Web Server Applications, Google for Developers (the redirect_uri must exactly match one of the client's authorized redirect URIs, else redirect_uri_mismatch; updated Sep 14, 2026, read Oct 12, 2026)](https://developers.google.com/identity/protocols/oauth2/web-server)
16. [Maintenance Mode, Heroku Dev Center (a static maintenance page for every visitor, error H80 in the logs; Scheduler jobs can still run; worker dynos keep running; dynos keep accruing billing hours; updated Feb 12, 2025, read Oct 12, 2026)](https://devcenter.heroku.com/articles/maintenance-mode)
17. [Maintenance mode behavior changed for worker dynos, Heroku changelog (worker dynos are idled with heroku scale worker=0; read Oct 12, 2026)](https://devcenter.heroku.com/changelog-items/104)
18. [gcloud reference, Google Cloud SDK 587.0.0 (--help of run services update --min-instances and --max-instances, run services update-traffic --to-revisions, scheduler jobs pause and resume with --location; read Oct 12, 2026)](https://docs.cloud.google.com/sdk/gcloud/reference/run/services/update)
19. Exodus team: a switch of two public names between two hosts on Oct 11, 2026 (records DNS-only with TTL 300; Google's and Cloudflare's DNS over HTTPS answered the new target 6 s after the record changed; the old host kept running for a week as the way back; the way back that needed a new Google certificate would cost up to an hour of HTTPS errors, the one that kept certificates in place none); read-only checks on Oct 12, 2026 (a VPN's resolver answered plain dig; the DNS provider's SOA gives 1800 s for negative answers; 20,081 Cloud Run requests to 8 services by hour of day, Oct 4 to 12, 2026; the exodus CLI 0.1.1 plan for a sample Rails app on Heroku)
