v2/. From that date on, v1/ receives nothing new. This page explains what
changes, when, and what to review on your side before the switch.
Everything else stays as it is today:
- The bucket, and the way you access it, with an AWS account or a Google account.
- The Parquet format and every column,
tenant_idincluded. - The 19 tables in the table catalog.
- Every folder already in
v1/. Nothing is moved or deleted, and you can keep reading it. - The storage rules: files still move to colder storage classes as they age, and to S3 Glacier Flexible Retrieval after 180 days.
All hours on this page are UTC, which is 3 hours ahead of Brasília.
snapshot_hour=03 is
midnight in Brasília and snapshot_hour=15 is noon. The same applies to etl_hour.What changes
The schema and table folders underv2/ are the same as under v1/. Inside each table,
the date folder gains an hour folder, and the manifest is written once per hour instead
of once per day.
Tables rewritten in full
These 16 tables keep arriving as a whole copy of the table on every delivery. The copy lands under an hour folder inside the date:snapshot_date= and snapshot_hour= holding
_SUCCESS. Since every copy is the whole table, you don’t need anything from v1/ to
read these tables after the switch.
Every hourly copy is kept for at least the last 7 days. For older days, only the copy
from the last hour of the day stays, so there is always at least one complete copy per
day, as there is today.
Tables delivered in parts
claudia_messages, claudia_prompt_revision and cloud_chat_messages keep arriving in
parts. Each hour adds a new folder under v2/ holding everything that arrived since the
previous delivery:
v2/ continues exactly where v1/ stopped, so the history is not copied: everything
delivered up to November 2 stays only in v1/, and everything after it arrives only in
v2/. To reconstruct a table, read the union of its folders in both prefixes:
- In
v1/,etl_date=__initial__and the dailyetl_date=folders. They no longer change after November 2, so you need to read them only once. - In
v2/, theetl_date=/etl_hour=folders, as they arrive.
claudia_messages or
claudia_prompt_revision changes after it was delivered, the new version arrives again
in a later hour folder, in v2/, even if the first version came in v1/. Keep the most
recent version of each row: the one in the latest folder, by etl_date and then
etl_hour, with the v1/ folders before the v2/ ones and etl_date=__initial__
before everything. The key is message_id on claudia_messages and
prompt_revision_id on claudia_prompt_revision. cloud_chat_messages sends each
message once.
etl_hour is the hour of the delivery, not of the event. To filter by when something
happened, use send_at on claudia_messages, and created_at on
claudia_prompt_revision and cloud_chat_messages.
One manifest per hour
complete: false does not mean the data is wrong. It means some table will arrive in a
later hour, and the latest hour holding _SUCCESS for it is still valid.
When it arrives
Each delivery holds the data as of about the start of the hour, and is usually available within 40 minutes after it. Check_SUCCESS or the manifest instead of relying on a fixed
time, as described in bucket layout.
The switch
There is no delivery between the two. The first hourly delivery of the tables delivered
in parts includes everything the last daily delivery did not, November 2 included, so
nothing is lost in the gap.
What to review
1
Point your ingestion at v2/
Replace
v1/ with v2/ in every path you read. After November 2, nothing new
arrives in v1/.2
Read only the latest hour of a table rewritten in full
Reading a whole
snapshot_date= folder returns up to 24 copies of the same table.
Pick the most recent snapshot_hour= holding _SUCCESS, and read only that.3
Add the hour to your catalog
If you declare partitions in Athena or Glue, define the tables under
v2/ with
snapshot_hour as a second partition column after snapshot_date, and etl_hour
after etl_date. Declare both as string.4
Keep the v1/ history of the tables delivered in parts
Read the
v1/ folders of claudia_messages, claudia_prompt_revision and
cloud_chat_messages once, if you don’t have them yet, and union them with what
arrives in v2/, keeping the most recent version of each row. Don’t treat one
etl_date= folder in v2/ as a complete day: a day is split across up to 24 hour
folders.5
Decide how often to read
You can read every hour, using the manifest of each hour as the trigger. If you keep
reading once a day, you still receive everything, as long as the steps above are in
place.
Prepare the switch ahead of time
You don’t need to change your ingestion on November 3. Deploy it any time before, with one rule: on every run, check whetherv2/ has received a delivery, and read from it if
it has. Until November 2 the job keeps reading v1/, and it switches by itself on the
first hourly delivery, even if that delivery arrives a few minutes late. Checking for
v2/ is safer than switching at a fixed time for that reason.
The example below is an AWS Glue job in PySpark. The same logic works in any engine or
orchestrator.
glue_job.py
- Tables rewritten in full, such as
claudia_conversation:latest_readyreturns the most recent folder holding_SUCCESS, which is a date inv1/and a date and hour inv2/. The same call works on both sides of the switch. - Tables delivered in parts, such as
claudia_messages: the history inv1/is always read, and the folders inv2/are added once they exist. The example reads the whole table on every run for clarity. In production, read thev1/history once and, from then on, only thev2/folders you haven’t processed yet. - Keep the latest version of each row. A row of
claudia_messagesorclaudia_prompt_revisionthat changes after delivery arrives again in a later folder. The window at the end keeps, for eachmessage_id, the row from the most recent folder. In an incremental pipeline, the same rule is an upsert by key. - Partition columns are read as strings.
etl_dateholds the literal__initial__inv1/, and turning type inference off keepsetl_date,etl_hourandsnapshot_houras strings on both sides, so the union lines up. - Permissions don’t change. The access you already have covers the whole bucket,
v2/included.