@@ -90,24 +90,44 @@ Pinning `--app-engine-service=default` is deliberate: the NEG routes straight to
9090service, ** bypassing ` gcp/dispatch.yaml ` ** — the dispatch file stays as the rollback
9191path for the direct App Engine domain mapping, not part of the LB path.
9292
93- ## 4. Backend services (timeout 600, full request logging)
93+ ## 4. Backend services (full request logging; timeout is platform-fixed)
94+
95+ Two platform constraints discovered at execution (2026-07-08), which changed this step
96+ from the original plan:
97+
98+ - ** ` timeoutSec ` cannot be set** on a backend service with serverless NEG backends
99+ (API error: "Timeout sec is not supported…"). Per the serverless NEG docs, the
100+ backend-service timeout ** does not apply — it is fixed at 60 minutes** for serverless
101+ backends, so the plan's ` --timeout=600 ` intent is exceeded by default; Cloud Run's own
102+ 300s request cap is the real binding constraint. Stage 5's long-request proof
103+ validates this empirically. (A ` timeoutSec: 30 ` may appear in describes — it is a
104+ display default and is ignored.)
105+ - ** ` portName ` is likewise rejected** , and older gcloud SDKs (≤ ~ 461) set it
106+ unconditionally at create time, making ` add-backend ` fail. Recent gcloud may work;
107+ the reliable path (used here) creates the service via the Compute REST API with the
108+ backend inline and neither field present:
94109
95110``` bash
111+ TOKEN=$( gcloud auth print-access-token)
96112for PAIR in " $BS_GAE :$NEG_GAE " " $BS_CR :$NEG_CR " ; do
97113 BS=" ${PAIR%%:* } " ; NEG=" ${PAIR##*: } "
98- gcloud compute backend-services create " $BS " --project " $PROJECT " --global \
99- --load-balancing-scheme=EXTERNAL_MANAGED --protocol=HTTPS \
100- --timeout=600 --enable-logging --logging-sample-rate=1.0
101- gcloud compute backend-services add-backend " $BS " --project " $PROJECT " --global \
102- --network-endpoint-group=" $NEG " --network-endpoint-group-region=" $REGION "
114+ curl -s -X POST " https://compute.googleapis.com/compute/v1/projects/$PROJECT /global/backendServices" \
115+ -H " Authorization: Bearer $TOKEN " -H " Content-Type: application/json" -d @- << JSON
116+ {
117+ "name": "$BS ",
118+ "loadBalancingScheme": "EXTERNAL_MANAGED",
119+ "protocol": "HTTPS",
120+ "logConfig": {"enable": true, "sampleRate": 1.0},
121+ "backends": [{"group": "https://www.googleapis.com/compute/v1/projects/$PROJECT /regions/us-central1/networkEndpointGroups/$NEG "}]
122+ }
123+ JSON
103124done
125+ # verify both services exist with their NEG attached:
126+ gcloud compute backend-services describe " $BS_GAE " --global --project " $PROJECT " \
127+ --format ' value(backends[0].group)'
104128```
105129
106- ` --timeout=600 ` : the default 30s would kill long ` /calculate ` requests; Cloud Run's own
107- request cap is 300s and App Engine's is longer, so 600 makes the LB never the binding
108- constraint. ** Validated empirically in Stage 5's long-request proof** — if the timeout
109- turns out not to be honored for serverless NEGs, that gate catches it before any DNS
110- change. Reminder: serverless NEGs have ** no health checks** — alerting (Stage 6) is the
130+ Reminder: serverless NEGs have ** no health checks** — alerting (Stage 6) is the
111131failover mechanism.
112132
113133## 5. URL map at 100/0, proxies, forwarding rules
0 commit comments