portfolio-press · applied-AI lab
one ladder, two clouds

The same thing, a different vocabulary.

That is the claim, and it is the kind of claim that sounds true whether or not it is. So the ladder on this site was built a second time on Google Cloud and the difference was counted rather than described. Most of it held. One part did not, and the part that did not was ours.

What actually moved

Lines, counted after the port rather than estimated before it.

209lines imported unchanged by both clouds The gate that recomputes every quoted figure, the engine that computes them, and the cost arithmetic. Not one of them contains cloud code.
331lines written for the second cloud Of which 131 are the orchestration definition. The Python that touches Google at all comes to 138 lines.
+25 / −32lines changed on the first cloud The price of the port, paid on the side that was already working. What it bought is below. Not counted: the 44 lines of narrator/prompt.py, which hold the prompt moved out of core.py rather than new text: the same strings, the retry hint renamed from private to public, and the user message wrapped in a function.

Step by step

Each row says what changed: the name only, the code, or the behaviour. Those three get collapsed into one word in most migration stories, and that is exactly where a slogan hides.

stepon AWSon Googlewhat changed
draftBedrock, Claude Haiku 4.5Vertex, Gemini 2.5 Flashcode
The SDK call and the usage record: 66 lines. The prompt, the retry hint and the message shape are one file, imported by both.
the gateLambdaCloud Runname only
The module that recomputes every quoted figure is imported unchanged by both clouds. A test asserts it by module path, not by comparing text.
the humanStep Functions, waitForTaskTokenWorkflows, await_callbackbehaviour
Same shape, different default: the callback wait defaults to 12 hours and is set explicitly here. The ceiling is one year on both.
the journalDynamoDBFirestorecode
44 lines. The record keeps the same field names, so a run from either cloud reads the same way.
publicationS3Cloud Storagecode
28 lines. The object key is built the same way.
logs and costCloudWatchCloud Loggingnot measured
Written, not yet run on Google, so this row has no number on the right-hand side.
the judgeoursoursnothing
Google's Gen AI evaluation service is the managed equivalent. It is named here as the thing we did not need, not as something we ran.

Where it stumbled, and it was not Google

The second cloud could not read the first one’s prompt without installing Amazon’s SDK.

The narrator package imported, at module load, a file that builds a Bedrock client. So any runtime that merely wanted to ask the same question of a different model had to carry a client for a service it would never call. Nothing about that is Google’s doing, and nothing about it was visible until something tried to leave.

The fix was small: the contract moved into a file with no imports beyond json, and the package now loads its client on demand. Both narrators import that one file, so the two clouds ask the model the same question by construction rather than by inspection. That is what the twenty-five added lines bought.

The general form is worth more than the fix. A system is portable in the places where it was never allowed to assume, and a vendor’s SDK imported at the top of a file is an assumption that costs nothing until the day it costs a rewrite. Ours cost twenty-five lines because the thing underneath was already separated. It is not always twenty-five.

Receipts

One side has run many times. The other has not run at all yet, and this page says so rather than leaving the column to look full.

AWS, measured

  • 10 runs published, every shipped figure recomputed from source.
  • 0 unverifiable numbers reached a reader.
  • 1 run of 11 timed out waiting for a human and shipped nothing.
  • About $0.003 of model spend per run.
  • The gate can be watched refusing one.

Google, not yet measured

  • The port runs end to end locally, against a stub in place of the model.
  • Twenty-three tests, none of which need an account, a network or credentials.
  • Only the gate has a service yet. The draft, notify and publish steps the orchestration calls are written as functions, not yet as services, and nothing writes the journal yet.
  • No cost per run, because no run has happened on Google.
  • No published report, for the same reason.

What would fill the right-hand column. A project, a billing link and one deploy. The stand is designed to go up, run once, record its receipts and come down again: a second cloud kept running for the sake of a demonstration costs money every month and attention every time it drifts, and what this page needs is a recorded run rather than a live address.

← the loop these numbers come from you are here · same ladder, two clouds next: the ladder itself →