Insights / Technical notes

Migrate Dynmap to 512px tiles: public checks and old R2 cleanup

How to check render areas, normal and zoom images, and R2 storage during a 512px tile migration. An eight-server, 89-map example explains pre-deletion checks and conditions for cost comparisons.

  • Technology
  • Cloudflare
Migrate Dynmap to 512px tiles: public checks and old R2 cleanup
Table of contents
  1. What to compare before migrating Dynmap tiles
  2. Migrate in stages with a bounded render area
  3. Verify the public map and storage separately
  4. Do not equate storage changes with a bill

We changed the map image format in a Dynmap setup that serves tiles from Cloudflare R2, then cleared the old data. The scope was eight servers and 89 maps. The critical part was the order: verify the new images in public before deleting the old ones.

What to compare before migrating Dynmap tiles

Compare normal and zoom tiles over the same render area before choosing 512px tiles. Record viewer requests separately from rendering writes. First inventory old prefixes; decide on deletion only after checking new public tiles and how to recreate old images from the world.

R2:Measuring storage and operations

Migrate in stages with a bounded render area

We standardized the production maps on 512px tiles. For 21 maps requiring additional rendering, we limited the area to a 2,000-block radius around the public center. We did not require a render of the entire world to finish; ordinary map updates continued during the transition.

We also improved retries after R2 communication failures, preservation of pending updates after write failures, and the distinction between a missing zoom tile and a read error. The Dynmap fork PR #9 records the fix for resuming zoom updates after restart. These changes do not prevent failures inside Cloudflare itself.

Retire old data only after verifying the new images Audit public output and storage before cleanup. Old images have no backup, and normal-operation cost savings are unverified.
  1. Bound the area and create new tiles Set the 512px scope and render area, then create new images while routine updates continue.
  2. Audit public images and storage Check regular and zoom images, web assets, live JSON, and the intended storage prefixes separately.
  3. Clean up legacy data after audit Remove legacy images and hashes after audit. They have no backup and must be rendered again from the world if needed.

Verify the public map and storage separately

After the switch, we checked one regular tile and one zoom tile for each of the 89 published maps: 178 images in total. We checked that the images were 512px and reviewed the web assets and live JSON updates. On R2, we audited whether storage paths matched the 89 production map prefixes and confirmed that 192 old regular and day-image prefixes were empty.

Only then did we remove 11,707,356 old image and hash objects, about 51.71 GB. The old image content has no backup; if needed, it must be rendered again from the worlds. We retained the current images, worlds, configuration, and JAR backups. A final audit, rather than the deletion process exit alone, confirmed that no old images, stage data, or old hash files remained.

Do not equate storage changes with a bill

Across two consecutive 24-hour windows that included the migration, successful PutObject calls fell from 240,835 to 90,423. Both windows included migration work, so the comparison is not a normal-operation reduction rate or a monthly cost estimate. The billed amount remains unverified.

For similar migrations, inspect R2 operation and storage metrics separately, then verify public display, current images, and old data in that order. Decide the deletion scope and recovery method before removing anything.