The 128 KiB floor is one of those costs that never shows up in a design review and always shows up in a billing review. The pattern I keep seeing is a lifecycle rule written by someone thinking in terabytes, applied to a bucket written by a pipeline thinking in events. Each decision is reasonable on its own and together they multiply the bill.
The usual fix upstream is compaction: batch the small objects into larger ones before they ever hit a colder tier, which also cuts the PUT and GET count. Same lesson as LSM trees, write small, merge later, and the storage tier you pick only makes sense once you know your object size distribution.