Recently, OpenAI’s Codex was found to have a logging issue: the program kept writing large volumes of logs to a local database, causing the files to grow continuously and generating far more disk writes than normal. Bugs like this are hardly new. A few years ago, most people would probably have deleted the files, restarted the app, and waited for the next release to fix it.
This time, however, the reaction was noticeably different. Instead of asking how much disk space remained, more people began wondering how much data had already been written to their SSDs, whether it might affect flash endurance, and how much more they would have to pay for the same amount of memory and storage when replacing their devices in the future.
The Codex bug may not be any more serious than other runaway logging incidents in the past. What has changed is that every pointless write suddenly seems to come at a price again.
As demand for AI compute continues to surge, memory manufacturers are increasingly prioritizing higher-margin, higher-demand products such as HBM, server memory, and enterprise SSDs. Consumer memory and SSDs are therefore receiving a smaller share of production capacity, while their prices continue to rise.
Memory and flash have always been cyclical industries, so price increases and declines are nothing unusual. What makes the current situation unsettling is that it no longer appears to be merely another inventory cycle. It is accompanied by a longer-term shift of industry resources toward AI infrastructure.
Even if prices eventually fall, consumers may not quickly return to the old assumption that large amounts of storage are practically free.
As storage stops feeling inexhaustible, developers may also need to reconsider their attitude toward resources.
When I first encountered computers, a common Apple II configuration had only 48 KB of memory. To make use of the additional 16 KB provided by an expansion card, developers had to arrange addresses, code, and data with great care, finding ways to make every byte count.
A game spanning tens of gigabytes today inevitably offers graphics, sound, world scale, and interactive complexity that would have been unimaginable in the Famicom/NES era. Yet its enormous size does not guarantee that it will be more enjoyable than a game measured in only tens of kilobytes.
This is not to say that modern software should not grow larger. What is worth examining is how, over many years, developers have grown accustomed to storage capacities increasing naturally and networks becoming ever faster. As long as there is still room for logs, caches, and temporary data, few people stop to ask why they exist or when they will be deleted.
Expensive SSDs will not automatically produce better software, nor will memory shortages suddenly make developers smarter. But once hardware can no longer be assumed to grow without limit, engineering questions that have long been overlooked begin to resurface.
I do not miss the days when developers had to struggle within a few dozen kilobytes.
What is worth recovering is not the scarcity itself, but an engineering habit that once felt natural and has gradually faded away:
knowing why every byte arrives—and when it will leave.
Recent Recommendations
Swift Task lifetime when an iOS device is locked
This Q&A comes from the Apple Developer Forums. The original poster found that a Swift Task making several sequential REST requests would sometimes complete normally after the device was locked, sometimes pause, and occasionally time out. DTS engineer Quinn “The Eskimo!” explains that Swift Concurrency runs entirely within the app process. Once iOS suspends that process, the worker threads executing the Task also stop, and the Task itself receives no additional background execution privileges.
This behavior can be especially confusing when networking is involved. If the app is suspended while a URLSession request is in progress, the request may fail because the connection becomes defunct. When the process resumes, developers may see a timeout or networking error rather than the Task continuing from where it paused and completing successfully. Quinn outlines four possible approaches: delay process suspension, stop in-flight requests before the app becomes eligible for suspension, allow requests to fail and implement retry and error recovery, or use a URLSession background session.
anyAppleOS in Swift 6.4
In the past, declaring availability for an API shared across Apple platforms required developers to list each platform and its corresponding OS version separately. Because version numbers differed across platforms for many years, these declarations were not only verbose but also prone to omissions and versioning mistakes. With Apple’s platforms adopting aligned major version numbers starting at 26, Swift 6.4 introduces anyAppleOS, allowing developers to describe APIs and code targeting Apple operating systems more concisely in @available, #available, and #if os(...).
Artem Mirzabekian introduces the new syntax and explains how it differs from platform-specific availability, canImport, and the platform declarations in Package.swift. He also shows how more specific availability rules can be combined with anyAppleOS when support arrives later on certain platforms or is unavailable altogether.
The Anatomy of a Reusable SwiftUI View
More developers are trying to make the APIs of their reusable SwiftUI views feel as close as possible to Apple’s own designs, but there is often no clear methodology for putting that goal into practice. Alexander Weiß shares his approach: first determine whether a component is semantic, describing a functional concept, or prescriptive, carrying a clearly defined visual form. From there, define its semantics, valid states, data flow, and interaction behavior. Components should also follow SwiftUI’s state-management conventions, use immutable values, Binding, and State appropriately, and treat accessibility, environment values, and stable view identity as part of the design rather than focusing only on the shape of the call site.
Using Card, Tag, and Rating as examples, the article demonstrates concrete implementations involving initializers, custom View Styles, and environment values. The central idea is not simply to imitate the appearance of Apple’s APIs, but to make custom components genuinely fit into the SwiftUI ecosystem through their composition model, state flow, interaction behavior, accessibility support, and environmental adaptation.
The hidden cost of unstable SwiftUI environment defaults
The @Entry macro makes custom environment values easier to declare, but directly using a reference-type instance as the default, such as @Entry var logger = AppLogger(), can cause unnecessary view updates. Whenever SwiftUI cannot find an injected value higher in the hierarchy and falls back to the default, it may create a new AppLogger. Although these objects behave identically, they are not the same instance, so SwiftUI may treat the environment value as changed and re-evaluate views that read it. Starting with Xcode 27, the compiler warns about this pattern, making a previously subtle issue easier to catch.
Natalia Panferova uses _printChanges() to demonstrate the issue directly and offers two solutions: keep the default instance in stable external storage, or declare the environment value as Optional and inject it explicitly at the app entry point.
I also analyzed this issue in SwiftUI Environment: Concepts and Practice. The root cause lies in how the @Entry macro generates the default environment value, allowing the default expression to be evaluated repeatedly whenever fallback access occurs.
Make Vertical Parallax for ScrollView in SwiftUI
Early 2D games created rich visual depth at very little cost by moving different image layers at different speeds. In SwiftUI, however, the difficult part of implementing scroll-based parallax is usually not calculating the offset, but continuously obtaining each view’s position within a ScrollView. In the past, this often required a combination of GeometryReader, custom coordinate spaces, and state propagation, resulting in more code and potentially causing unnecessary view updates when handled poorly.
The introduction of visualEffect has greatly reduced the complexity of building these effects. codelaby demonstrates how to read a view’s geometry directly inside visualEffect and apply an offset based on its scroll position, without maintaining additional state or changing the view’s original layout.
Tools
swift-span-algorithms: Adding Algorithmic Capabilities to Span
When working with contiguous memory, Swift developers traditionally had two main choices. Types such as Array and ContiguousArray own their storage and are safe and convenient, but may involve copying, reference counting, or additional allocation. Pointer types such as UnsafeBufferPointer offer low overhead and greater control, but require developers to ensure that the underlying memory remains valid and that every access stays within bounds.
Introduced in Swift 6.2, Span<Element> fills the gap between these approaches. It is a non-owning view over contiguous memory: it does not retain the underlying storage, but relies on compiler-enforced lifetime tracking and bounds checks to provide safe access. In Swift 6.2, however, Span does not yet offer the same breadth of algorithms available to Collection and Sequence.
David Retegan created swift-span-algorithms to fill that gap. The library adds searching, comparison, trimming, chunking, sliding windows, splitting, cursor-based operations, and other utilities for Span, RawSpan, MutableSpan, and InlineArray. It is designed around zero hidden allocations and constant additional space, extending Span’s algorithmic capabilities while continuing to respect its lifetime constraints.