<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Advances in Computing: Queue: In Practice]]></title><description><![CDATA[insights from ACM Queue, written by engineers, for engineers]]></description><link>https://theofficialacm.substack.com/s/queue-in-practice</link><image><url>https://substackcdn.com/image/fetch/$s_!pM9H!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6646612-d04c-4756-9715-1080ffd8e327_621x621.png</url><title>Advances in Computing: Queue: In Practice</title><link>https://theofficialacm.substack.com/s/queue-in-practice</link></image><generator>Substack</generator><lastBuildDate>Sun, 12 Apr 2026 11:02:24 GMT</lastBuildDate><atom:link href="https://theofficialacm.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[The Official ACM]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[theofficialacm@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[theofficialacm@substack.com]]></itunes:email><itunes:name><![CDATA[The Official ACM]]></itunes:name></itunes:owner><itunes:author><![CDATA[The Official ACM]]></itunes:author><googleplay:owner><![CDATA[theofficialacm@substack.com]]></googleplay:owner><googleplay:email><![CDATA[theofficialacm@substack.com]]></googleplay:email><googleplay:author><![CDATA[The Official ACM]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Data Analysis: Why Is It So Complicated?]]></title><description><![CDATA[Why your models are incomplete and rife with inaccuracies, assumptions, caveats, and limitations]]></description><link>https://theofficialacm.substack.com/p/data-analysis-why-is-it-so-complicated</link><guid isPermaLink="false">https://theofficialacm.substack.com/p/data-analysis-why-is-it-so-complicated</guid><dc:creator><![CDATA[The Official ACM]]></dc:creator><pubDate>Wed, 01 Apr 2026 11:06:59 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!7Wrt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever asked a very simple question of data scientists, only for them to spend way too long doing analysis and then refuse to give you a straight answer, hedging with, &#8220;It depends&#8221; or &#8220;There is some evidence for&#8221;? Or maybe you were building a dashboard and you just wanted to aggregate analysis outputs, and instead of handing over their models, the data science people kept grumbling about &#8220;needing expertise to use the model outputs&#8221;? Have you then thought: This should have been simple&#8212;<em>why is it so complicated?</em></p><p>This article aims to give you a sense of the depth and breadth of why it&#8217;s so complicated to conduct and interpret data analysis. It begins with an overview of the purpose of data analysis, reviews different components of data and modeling and how each component introduces complexity to the process of analysis, discusses interpretation of analytic results, and concludes with a few recommendations for productively managing all of these challenges.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7Wrt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7Wrt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp 424w, https://substackcdn.com/image/fetch/$s_!7Wrt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp 848w, https://substackcdn.com/image/fetch/$s_!7Wrt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp 1272w, https://substackcdn.com/image/fetch/$s_!7Wrt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7Wrt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp" width="1456" height="887" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:887,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:113894,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://theofficialacm.substack.com/i/189920659?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7Wrt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp 424w, https://substackcdn.com/image/fetch/$s_!7Wrt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp 848w, https://substackcdn.com/image/fetch/$s_!7Wrt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp 1272w, https://substackcdn.com/image/fetch/$s_!7Wrt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb35188c3-155f-40c6-8607-da390b9e7241_1898x1156.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Queue: In Practice! Subscribe for free to receive new posts.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><h3>First: What <em>is</em> Data Analysis?</h3><p>Data analysis underlies most decisions, even if you&#8217;re not directly aware of it. If you know you have a family history of heart disease, should you eat oatmeal or bacon for breakfast? If you want to sell your house, how high should you set the price?</p><p>Fundamentally, these questions are about <em>prediction:</em> If I eat oatmeal, am I less likely to die of a heart attack? If I price my house at $x, will it sell, and how quickly?</p><p>Basic data analysis involves just <em>describing</em> data: Maybe oatmeal eaters are five percent less likely to die of heart attacks than bacon eaters. This is great to know, but it would be far more powerful to understand <em>why</em> these dietary choices are related to cardiac outcomes. Oatmeal reduces the odds of a heart attack <em>because</em> its soluble fiber lowers cholesterol. Understanding this mechanism means that you can predict which other foods might be heart-healthy because they&#8217;re high in soluble fiber.</p><p>Ultimately, if you understand the mechanisms that generate your data, you can make better predictions, and thus better decisions. Data science can of course be wielded for other purposes, but this article focuses on data analysis used to inform decision-making.</p><p>Data analysis rests on the basic assumption that your data <em>means</em> something. Your data reflects something real in the world, and analysis is the process of trying to describe the world and its mechanisms based on the data you collected.</p><p>Sometimes you have a clear idea what your data means, either because you understand the process that generates the data, or because you have scoped the system that you&#8217;re observing very tightly. Even systems that seem to be well scoped and deterministic, however, invariably collide with the chaotic nature of the world and human behavior and end up with startlingly weird edge cases, exceptions, and other messiness. So, in most cases, figuring out what data means becomes the primary challenge of data analysis.</p><div><hr></div><h3>Why It&#8217;s So Complicated, in Short</h3><p>Data analysis is complicated for the following basic reasons:</p><p>&#8226; The <em>world</em> is complicated.</p><p>&#8226; Your view of the world is incomplete and inaccurate.</p><p>&#8226; Data and tools used to analyze data come with assumptions, caveats, and limitations.</p><p>&#8226; Interpreting a result is a lot harder than getting a result.</p><p>Data analysis can be simple if you are willing to ignore these problems and just slap your data into some equations, but the result will not help you much.</p><div><hr></div><h3>Data Science Fundamentals</h3><p>The following sections dive into the fundamental components of data science, exploring why they&#8217;re complicated and how to successfully navigate their impact on your work.</p><h4>Populations and samples</h4><p>In statistics, a <em>population</em> refers to all of whatever you&#8217;re interested in and can be defined very broadly (e.g., hospitals) or quite specifically (e.g., hospitals in California that treated patients for motorcycle accidents in March 2025).</p><p>A <em>sample</em> is some subset of the population that you can actually collect data about, like 10 hospitals in California that have signed a data-sharing agreement and set up reporting streams to your database. By analyzing data from your sample, you hope to learn something that you can then extrapolate to the entire population.</p><p>Accordingly, the more representative a sample is&#8212;the more accurately it reflects the properties of the entire population&#8212;the better you can accurately extrapolate whatever you learn from the sample. If your sample of 10 California hospitals are all in rural areas, then the things that you learn from their data might not be true for urban hospitals. In pure research, large random samples are the gold standard, because they are likely to be representative of the population; but, in real-world applications, you might not have a choice about which subset of the population opts to provide data.</p><p>In closed, well-scoped systems, you might have data about your entire population (e.g., log files from all of your Amazon EC2 [Elastic Compute Cloud] instances), but in systems that collect data from out in the world, it is rare to have access to an entire population. If you somehow <em>do</em> have access to your entire population&#8217;s data, then you might be getting far more data than you can practically analyze, and you might need to downsample to make analysis tractable.</p><h4>Measurements and operationalization</h4><p>Data is produced by taking <em>measurements</em>, most of which are <em>proxies</em> rather than direct measurements. For example, a mercury thermometer doesn&#8217;t measure the temperature in a room directly; instead, it measures the height the column of mercury reaches as a result of expanding or contracting in response to the room&#8217;s temperature. For another example, a survey can&#8217;t measure customer experience directly; instead, it measures the numbers that a customer chooses in response to questions.</p><p>Measurements vary in how well defined they are and how well their definitions map to the world. You know exactly what your thermostat measures: Each degree on the Fahrenheit thermostat is the same as every other degree on that thermostat&#8212;and on every other thermostat.</p><p>In contrast, you know very little about what your customer-experience survey measures. The measurement is not well defined: What does <em>satisfied</em> even mean? Does it mean the same thing to everyone? Worse yet, it might not even measure satisfaction with your product at all, because a bad survey response could just reflect a customer having a bad day, or feeling spiteful, or responding randomly.</p><p>In real-world systems, what you want to measure is often abstract or ambiguous, so it isn&#8217;t obvious what data you should collect or how. The process of deciding how to turn the abstract thing that you want to analyze into a definition of something you can measure is called <em>operationalization</em>.</p><p>Maybe you want to know how many people in a city are infected with influenza. You can&#8217;t measure infection directly&#8212;no tool can peer into a living body&#8217;s cells and see the viral machinery at work&#8212;but you can operationalize infection as measures that might reflect infection. You could ask people about symptoms, assuming that infection produces symptoms and that self-report of symptoms is accurate; you could aggregate clinic and hospital data, assuming that infected people seek medical care and that those facilities will generate records that indicate influenza; you could even look at sales of tissues and decongestant medicine, assuming that infected people will purchase more of these products.</p><p>All of these approaches are valid operationalizations of influenza infections, but each measures something different and requires you to make different <em>assumptions</em> about that measurement&#8217;s relationship to infection. This is a necessary evil&#8212;every operationalization requires you to make assumptions&#8212;but any assumption will be more or less true under specific circumstances. For example, a more severe strain of influenza could lead to a greater proportion of infected people going to medical facilities, which, in that situation, might make medical records a better measure than tissue sales.</p><p>One challenge in operationalizing abstract concepts is that most interesting things about the world don&#8217;t fall into cleanly defined categories, so ground truth may not even exist. Even something like &#8220;being infected&#8221; with the flu is very ambiguous: Should a person count as infected when a single one of their cells has been taken over by the influenza virus? A hundred of their cells? A million? How do you define which people your measure should count?</p><p>Ultimately, <em>how</em> you operationalize a variable must be driven by the bigger picture of what you care about. If you&#8217;re collecting data about the flu because you want to know about the burden on healthcare systems, then you probably don&#8217;t want to count asymptomatic people as infected, regardless of how many of their cells are infected.</p><h4>Error</h4><p>Measurement error is the difference between what you measure and reality. Because most things cannot be measured directly, and because the world is a complicated place, error is inescapable. The following three sections review several of the many sources of error in data analysis.</p><h5>Error in the measurement</h5><p>&#8226; The resolution of a measurement device (e.g., an analog thermometer marked every five degrees) limits the precision of measurements, while inaccuracies in a device (e.g., a mislabeled analog thermometer) limit the accuracy of measurements.</p><p>&#8226; Even very precise measurements might not measure what you want to be measuring, or might not measure it completely or correctly. For example, speeding is nearly universal in the United States, but drivers who speed minimally are unlikely ever to be stopped by law enforcement, and thus no data is generated about their speeding. You may correctly count how many tickets are given for speeding, but that count does not reflect the true rate of speeding, because so many speeding drivers are not ticketed.</p><p>&#8226; Your assumptions about the relationship between a measure and reality may be incorrect or incomplete. For example, your software for a wearable device might assume that a user&#8217;s spiking heart rate reflects psychological distress, but the spike might instead be caused by physical activity, excitement, or even a cup of strong coffee.</p><h5>Error in the situation around the measurement</h5><p>&#8226; Basic human mistakes (like typos or mixing up date formats) are more common than you might think. Even automated systems inevitably experience edge cases or exceptions that require humans to intervene manually and thus introduce mistakes.</p><p>&#8226; Contextual factors may interfere with a precise and accurate measure that does measure what you want. For example, a person who is fatigued while taking a math test might score lower than their true level of knowledge should allow.</p><p>&#8226; Datasets often represent a snapshot in time, and as time ticks relentlessly onward, the data will age and might diverge from current unmeasured reality. The data might have been accurate when collected, but not at later dates.</p><h5>Error in the bigger picture</h5><p>&#8226; Systematic biases are ways in which certain data is more likely to be recorded, which leads to datasets that may be correct but incomplete and can thus be misleading in sneaky ways. In the previous speeding-ticket example, drivers of flashier cars might be more likely to be ticketed, leading us to believe that drivers of flashy cars are more likely to speed.</p><p>&#8226; System-level events can also impact data, from a fire that consumes boxes of records in a warehouse to hospital reporting systems switching to a new coding system. The truly insidious thing about these errors is that you may not be aware of them; you can&#8217;t see missing data, and often you have no way of knowing that miscoded data is wrong.</p><p>&#8226; Events in the world usually don&#8217;t document themselves: The data you can acquire about an action or process is often generated secondary to the task itself, like paperwork filled out by a nurse to document administering a vaccination. <em>Doing</em> a task is typically higher priority than producing data <em>about</em> the task, so the data will be subject to basic errors (like typos), delays, and biases (e.g., busier clinics or those with lower funding might produce less accurate or timely data because they have fewer people and not as much time to complete paperwork).</p><h4>Oh man, that&#8217;s a lot of error! What can I do about It?</h4><p>Ultimately, you can&#8217;t guarantee that your data is (a) measuring what you want to measure, (b) measuring that thing correctly, (c) measuring that thing in an unbiased way, and (d) not missing or wildly wrong because of system-level issues. There is no comprehensive checklist of ways to detect or address error; often the best you can do is be aware of these sources of error, be vigilant about their impact on your data, and think carefully about how to mitigate error you do detect.</p><p>&#8220;Think really hard about it&#8221; can be frustratingly unhelpful advice to receive, so here are a few strategies that can help address <em>some</em> of the sources of error in your data:</p><p>&#8226; Incorporating external sources of information (such as regular check-ins with human stewards of data feeds) can help detect missing or erroneous data.</p><p>&#8226; Deploying automated anomaly detection on as many facets of data you can think of, from distribution of values to frequency of data dumps, is not a replacement for vigilance but can be a useful tool for monitoring.</p><p>&#8226; Incorporating multiple measures of the same or similar data can help you identify issues. For example, if wastewater signals indicate that influenza rates are rising, but hospital data shows no increase in flu cases, then there might be a problem with a data feed or analysis pipeline.</p><p>&#8226; Estimating the prevalence of errors, even roughly, can help you calibrate your confidence in your analysis or inform you whether to include a particular factor in modeling. For example, if a variable is missing in 50 percent of cases, you might not want to include it; if it&#8217;s missing in five percent of cases, maybe it&#8217;s okay to include with the caveat that it is a source of error in the model.</p><p>&#8226; As you gain familiarity with your data, you will discover errors that are likely specific to your situation. For example, you may ingest inventory records that don&#8217;t specify units or files that contain both MMDDYY and DDMMYY date formats but don&#8217;t indicate which record uses which format. Documenting these issues and bundling that documentation with the data can help ensure that all parties handle the data correctly.</p><p>&#8226; If you don&#8217;t have a deep understanding of the source of your data, find someone who does and pick their brain about the data, the data source, how other fields or industries deal with the data, and potential sources of error. Experts can provide valuable context as well as lessons learned from the mistakes they&#8217;ve made with similar analyses.</p><p>Nothing on this list can address error from systematic bias, or contextual factors that influenced measurements, or how closely your operationalization gets to the reality of what you want to measure. If you could wave the magic data wand to get perfectly measured and operationalized variables collected from a perfectly representative sample free of human mistakes and systematic bias, the thing that you&#8217;re measuring is still a thing <em>in the world</em>, and the world ranges from probabilistic to downright chaotic. The world is a messy place, so data about it will be messy too, in a very fundamental way.</p><p>Do your best to reduce error in your data, but remember that the presence of error is not a solvable problem.</p><h4>Summary of the fundamentals</h4><p>Where do we find ourselves in trying to understand the world using data? First, we have to figure out what measurements to make and which are likely to be proxies of what we&#8217;re actually interested in. Then we get inaccuracies introduced by the proxiness of our measurement, the nature of the measurement itself, the system collecting the measurements, and random chance. And all of these measures are collected about only a sample or subset of the world that we&#8217;re interested in. Great.</p><p>To make things worse, once we have data, we have to do something with it so, next let&#8217;s talk about models.</p><div><hr></div><h3>What Is a Model?</h3><p>In data science, a model is an abstraction of something in the world. A model typically includes input variables, relationships among the variables, and output variables that are calculated or estimated based on the inputs and their relationships. The parameters that define the strength and direction of relationships among variables are typically fit or trained based on historical data but may be defined by the modeler.</p><p>For a simple example, a model of sales on a website might represent people and day of the week, and parameters estimating the relationship between purchases and day of the week could be calculated as each day&#8217;s average from the past year. A website selling office supplies and one selling hobbyist fishing equipment might be modeled using the same simple structure (people and day of the week), but training on past data would lead to different parameters: The office-supply model might estimate higher purchasing on weekdays, while the fishing-supply model might estimate higher purchasing on weekends.</p><p>For a more complex example: An inventory logistics model might include many inputs, such as how many of a product can fit on a truck, when and in what quantity the product arrives at a warehouse, and how far away the retail sites are that must receive the product. The model structure might assume that the product arrives in bulk shipment at the warehouse, where it is packed onto trucks and shipped out to the retail sites. With historical data about how many trucks per day can be packed and shipped, you could build a model that estimates outputs of how quickly and how much product can be distributed to the retail sites.</p><p>As shown in this example, you need data from the past to build the model, but usually you also need to be able to collect the same kind of data in the future so you can use the model to support decision-making. For example, there&#8217;s not much point in including warehouse staffing levels (that you have historical data on) in your inventory logistics model if you know that you won&#8217;t have access to staffing data in the future.</p><p>The availability of data is thus a major consideration when deciding which factors to include in a model.</p><h4>What goes into a model?</h4><p>As the adage goes: All models are wrong, some models are useful. The goal of developing a model is to make one that is more useful than wrong.</p><p>Models that capture the subset of the world that you need to answer your question are useful, so a lot of the challenge (and artistry) in data science lies in identifying the factors that should be included in a model. Four major components contribute to this decision: knowledge about how the modeled thing works in the world, knowledge about how the available data is generated, knowledge about modeling, and a clear understanding of the question the model should answer or the decision it should inform.</p><p>Models of things in the world are vanishingly unlikely to include every factor that impacts the output, because the world is complicated, and collecting data is hard.</p><p>Maybe you want to investigate the impact of homework on kids&#8217; performance in school, so you ask a teacher for data about how many assignments each student in their class completed as well as their test scores. You fit a simple linear regression model to your data and find that the line is flat: There is no relationship between homework (as measured by how many assignments are completed) and performance (as measured by test scores).</p><p>What other factors might be relevant that are not accounted for in the model? Maybe the subject is important, such that homework helps with math but not with social studies. Maybe factors about the students are important, like whether they ate breakfast that morning.</p><p>It&#8217;s only worth including a factor, however, if the additional value that it brings to the model outweighs the error introduced by its inclusion. Whether a student ate breakfast at all is likely much more important (and easier to measure accurately) than what percentage of their meal was protein or how fast they ate it. An infinite number of variables could theoretically be measured about a given situation (Did the meal include beans? What kind? Were they grown in high-nitrogen soil?, etc., etc.), but most won&#8217;t have much impact on the outcome.</p><p>This is actually great news, because collecting data can take a lot of time and resources. Deciding which factors to include in the model thus needs to account for not only which factors are <em>important,</em> but also which are <em>practical.</em></p><h4>The world is complicated. Should I make complicated models?</h4><p>More complex models are not necessarily better. The short reason: garbage in, garbage out. The longer reason: Every variable is associated with error, assumptions, estimations, and caveats. Slapping more variables into a model without a deep understanding of those variables, their sources of error, and an accurate view of how they relate to other variables or the world will increase the complexity and uncertainty around your model without necessarily adding value.</p><p>Models that are too complex can also lead you astray in interesting ways, such as overfitting. As previously discussed, data is an incomplete and error-filled sample of the world; if you build a model that represents that one sample really well, it is unlikely to fit the next sample very well, because that next sample will be incomplete and error-filled in different ways.</p><p>More complex models don&#8217;t necessarily give you better answers, even if you have a good understanding of the <em>why,</em> good data to feed the model when it&#8217;s deployed, and continuing resources to maintain the model to account for changes in the world, the datasets, and your questions.</p><p>Critically for the software engineers who may be tasked with code management, complex models are more difficult to understand and reason about. This makes them much more difficult to debug, maintain, and update. As a result, they&#8217;re also more likely to produce unintended behavior, leading to exciting surprises when they are deployed to production.</p><p>This article has now addressed the major pieces involved in data analysis. Next, let&#8217;s tie it all together by looking at the process as a whole.</p><div><hr></div><h3>What Does the Data Analysis Process Actually Look Like?</h3><p>The complications discussed here are extensive and touch every step of data analysis from beginning to end. What does this process look like in practice?</p><p>As a data scientist approaching a new analysis, your first task is to understand the goal: What question must be answered or what decision must be informed by your analysis? Is there any context around risk and stakeholder motivations that can help you understand the decision to be made? This framing drives every downstream decision you make in your analysis, so be as crystal clear as possible.</p><p>Then you engage in a potentially lengthy process of finding data. You research the problem space to understand which factors are most important and which are not. You might design new measures and collect new data or seek out existing datasets; for each dataset you think deeply about what the data actually measures, understand potential error in the data, and do the legwork of acquiring files or feeds and cleaning them.</p><p>You figure out what kind of model is best suited to the problem and is feasible given constraints of data, time, processing power, and assumptions. You identify variables that are critical but not available, how their absence will impact modeling, and what relationships should be constructed between factors in your model. You implement, test, and debug the model.</p><p>Finally, success! At the end of this process, you have achieved a model that you&#8217;re confident in: You understand all of the variables in it and how they relate and what&#8217;s missing (and why), and you can brief decision-makers on the strengths and weaknesses of the model, caveats around applying it, and sources of error. But before you can use it for decision-making support, there is just one more tiny piece to consider, which is: <em>everything else</em>.</p><h4>Data analysis means nothing alone</h4><p>Specifically, you must consider <em>context</em>, or the additional information you need to evaluate or interpret the output of your model. The requirement for understanding the context around an analysis is a major gatekeeper in accurately using data science (and incidentally, it&#8217;s also why data scientists get so grouchy when asked to chuck their model output onto a dashboard, viewable by anyone with zero context).</p><p>Context here can take many forms, but generally it means information that tells you what is <em>normal</em> or <em>good</em> or <em>bad</em> so you can evaluate the numbers that come out of your analysis. That context can come from subject-matter experts, historical data, other ways of looking at your datasets, or other data sources entirely.</p><p>For a simple example, say you build a model, crunch the numbers, and end up with a figure showing exponential increase. Is this situation good or bad? If the data represents the number of spiders in your desk drawer, probably bad. If the data represents the number of dollars in your bank account, probably good.</p><p>For a more complex example, maybe you&#8217;re the U.S. federal government and you&#8217;re distributing a limited supply of COVID-19 medicine during the pandemic, and you want to know if any state is stockpiling the medicine instead of distributing it to patients. What does <em>stockpiling</em> mean? A state having more treatments stored up than it should have. Well, how much <em>should</em> it have?</p><p>You could make a huge model that predicts <em>need</em> for medicine by estimating how many COVID-19 cases will occur on what timeline in each state based on past case counts, vaccination rates, and assumptions about future holiday travel, heat waves, school vacations, and transmission rates of future variants. Then you could estimate how many of those cases would seek treatment and compare each state&#8217;s stored quantity of medicine to that number: If a state is storing more medicine than it needs, then it must be stockpiling.</p><p>But your model has a zillion assumptions built into it. What if states are calculating how much they need using different assumptions? They could be making very reasonable models but reaching very different conclusions than you do about how much medicine they should be storing.</p><p>The point of this huge model is to provide the context of &#8220;how much should states have&#8221; by estimating how much they need, but this approach introduces a heap of error and assumptions. Instead, you could just stick with the data you are confident in and use the states as context for <em>each other</em>. You could build a simple model that normalizes each state&#8217;s stored supply of treatments by the population of that state to estimate how much medicine each state has <em>per person</em>, then compare those numbers across states. If most states have 0.1 doses per person, but one state has two doses per person (20 times more!), maybe you can conclude that that state is stockpiling. You can certainly be more confident in the numeric result, which rests on only two numbers per state that you probably have high confidence in: population size and current inventory.</p><p>But wait. You still need more context before concluding that a state is being greedy. Maybe there&#8217;s a good reason for having so many doses: Maybe that state manages its supply differently, or has a much more vulnerable population, or is expecting a bad hurricane season that would impede future deliveries, or any of an infinite universe of sensible reasons. You need to understand <em>why</em> that state has so many doses per person in order to make any kind of decision about it.</p><p>In summary, the requirement for context in interpreting analytic results cannot be overstated: Your numbers mean <em>nothing</em> alone. Context is what allows you to actually use analytic results to support your decision-making by telling you if your result is expected or surprising, good or bad, and help you understand <em>why</em> you found that result so you can make better decisions about it. The flip side of this principle is that analysts (and consumers of analysis) <em>must not make assumptions about context.</em> The real danger here is jumping to a conclusion about context or interpretation but not realizing that it&#8217;s an assumption. Failing to identify assumptions in a thought process is a stunningly easy error to make and can lead to wild misapplication of otherwise very nice analytics.</p><div><hr></div><h3>Closing Remarks</h3><p>The messiness of the world is incurable, but two principles about the way you approach data science can make the whole endeavor much more valuable to you.</p><p>First, decision-makers need to understand the fundamentals of a model in order to effectively or accurately use its output. Specifically, what factors were accounted for, what factors <em>weren&#8217;t</em> accounted for, and how much will the exclusion of those factors impact the outcome? How does the model approximate interactions between factors, and how critical are those assumptions to the output? Bundling this kind of metadata about an analysis with the analytic results makes the results much more valuable (and usable) for decision-makers.</p><p>Second, as much as we all love data, it is not a magic bullet and must be considered as part of a bigger picture. If you could wave the magic analysis wand, fix all of the massive and fundamental issues discussed here, and generate a completely correct answer to a data-analysis problem, what would you do with it? If an analyst could tell you with total certainty that eating bacon instead of oatmeal for breakfast today raises your odds of a heart attack by exactly 0.0002 percent, what would you do with that extremely precise number? How would you turn that analytic result into a decision?</p><p>Data science feels very authoritative and objective&#8212;It&#8217;s got numbers! Graphs! Fancy equations!&#8212;so it&#8217;s easy to think of it as more precise and trustworthy than other sources of information. As discussed at length here, however, even the most rigorous of analyses rest on all kinds of squishy judgments and are beset by error at every step. Ultimately, data analysis is a deeply valuable and worthwhile enterprise that can dramatically increase the quality of decision-making&#8212;but it&#8217;s only one piece of the puzzle.</p><div><hr></div><p><strong>Alice Jackson</strong> is the founder of Colorpoint Data, specializing in helping people turn their data into information. Previously, she worked as a senior scientist and project manager at the Johns Hopkins Applied Physics Lab, applying her skills in experimental design, analysis, and scientific communication to projects ranging from human performance to public health. She holds a Ph.D. in cognitive neuroscience from the University of Maryland.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/p/data-analysis-why-is-it-so-complicated?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Queue: In Practice! This post is public so feel free to share it.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/p/data-analysis-why-is-it-so-complicated?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://theofficialacm.substack.com/p/data-analysis-why-is-it-so-complicated?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><p></p>]]></content:encoded></item><item><title><![CDATA[Smart-and-fast thinkers are good, but slow-and-steady thinkers are great]]></title><description><![CDATA[The shiniest tool might cut the deepest.]]></description><link>https://theofficialacm.substack.com/p/smart-and-fast-thinkers-are-good</link><guid isPermaLink="false">https://theofficialacm.substack.com/p/smart-and-fast-thinkers-are-good</guid><dc:creator><![CDATA[The Official ACM]]></dc:creator><pubDate>Wed, 18 Mar 2026 11:00:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!uaI5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uaI5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uaI5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif 424w, https://substackcdn.com/image/fetch/$s_!uaI5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif 848w, https://substackcdn.com/image/fetch/$s_!uaI5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif 1272w, https://substackcdn.com/image/fetch/$s_!uaI5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!uaI5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif" width="626" height="626" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:626,&quot;width&quot;:626,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:12335,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/avif&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://theofficialacm.substack.com/i/189919953?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!uaI5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif 424w, https://substackcdn.com/image/fetch/$s_!uaI5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif 848w, https://substackcdn.com/image/fetch/$s_!uaI5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif 1272w, https://substackcdn.com/image/fetch/$s_!uaI5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42f39b95-7ead-4755-9a04-72e4acae1b27_626x626.avif 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><strong>Dear KV</strong>,</p><p>I&#8217;ve been asked to mentor a new engineer on our team and it&#8217;s proving to be quite a challenge. While they are very bright and eager, they also are very excitable and seem to have a thing for reaching for the wrong tool at the wrong time. In particular, they believe that all the problems in our system can be solved by making modifications to low-level software, right down to the operating system and driver level, when many of the problems could be solved by simply making changes to our libraries and user-space programs. I suspect our manager has assigned me to be the new engineer&#8217;s mentor because this is the exact area in which I work and there are hopes I&#8217;ll be able to &#8220;train them up&#8221; to become another &#8220;one of those systems people.&#8221; I&#8217;m happy to do so, but how do you get someone like this to slow down and consider what they&#8217;re doing? I feel like I&#8217;m trying to prevent a toddler from knocking over the furniture.</p><p style="text-align: right;"><strong>Toddled</strong></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Queue: In Practice! Subscribe for free to receive new posts.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><strong>Dear Toddled</strong>,</p><p>Ah, the lure of low-level systems programming. No data structures, no debuggers&#8212;nothing but you and a compiler (or maybe just the assembler) in silent solitude, making the lights blink. Who could deny the allure of telling tall tales at the bar after a hard day of toil conquering single bit flips, corrupted storage blocks, and priority inversions? Huzzah!</p><p>Of course, we know this is not at all what programming at the systems level is about. Instead, it involves stumbling around with a dim, smoky torch in a dangerous, dark cave armed with only a stick and hoping not to meet Grendel or the Minotaur.</p><p>Smart-and-fast thinkers are good, but slow-and-steady thinkers are great, and the former can become the latter with a little bit of practice.</p><p>Since it seems you&#8217;re the systems guru in your group, or perhaps for your whole company, it really is in your interest to train up a partner-in-systems-crimes to help you with what are surely some difficult problems. But, first, you must teach them to reach for the right tool at the right time.</p><p>No systems programmer in their right mind&#8212;and there are still a few of us in our right minds&#8212;reaches first for a kernel modification. The tools available to study problems are, for the most part, far richer above the user/kernel boundary than below. Also, new ideas are easier to try out in a user-space library or program, where the price of failure is that you crash a single program, instead of waiting 10 minutes for a whole server to reboot. One might think a few experiences like these would be enough to teach your young prot&#233;g&#233; an important lesson. Not even KV would suggest throwing a chaos monkey at your prot&#233;g&#233;&#8217;s test machine to teach them that lesson, but it is tempting.</p><p>A more positive way to convey this lesson would be to show them the set of tools they have at their disposal and then ask questions that will lead them to use those tools. Debuggers, profilers, and tracing systems long ago made the tracking of problems in code a much more productive endeavor. When KV was a very young person, he had a boss who required him to run each new program in the debugger first, before ever running it bare. That was an important lesson and one that I encourage many people to start with.</p><p>This can now be expanded to include running the program under a profiler first, even if the program is brand new. Storing the output of these runs allows you to track the evolution of code over time and can even prove helpful years later, after a system has been in the field for a while as a baseline for comparison. Giving yourself a way to know when a program started to perform differently will surely be of benefit to you at some point.</p><p>If the richness of tooling isn&#8217;t sufficient to convince your prot&#233;g&#233;, you can try showing them the commit history and relevant bugs for a piece of operating-system code. Have them summarize a year or two of changes to a NIC (network interface card) driver (the Intel e1000 is hilarious) and then ask them what they have learned from the experience. If they don&#8217;t come back with, &#8220;Kernel programming is hard, and spurious changes are to be avoided,&#8221; make them review <em>five</em> years of commits instead.</p><p>When it comes to your prot&#233;g&#233;&#8217;s own code, make sure you force them to document what they&#8217;ve changed, no matter at what level, in lengthy detail in each commit message. &#8220;Fixed bug&#8221; (something KV wrote about decades ago) is not a commit message. It&#8217;s a slap in the face to every programmer who reads it, effectively telling them, &#8220;Go figure it out yourself.&#8221; Good commit messages show that the person who wrote them understood both the problem and the solution to the problem. In the fullness of time, it may turn out their take on the problem was incorrect, but at least there will be something to reference that shows what the thought process was.</p><p>People, alas, mostly learn from experience, when they learn at all. You will need to figure out the right set of experiences to convince your prot&#233;g&#233; to choose the right tool for the job, as opposed to whatever they might think would be the coolest.</p><p>We both know that any person who works on low-level systems will always say, &#8220;The last tool you reach for is the one that can cut you most deeply.&#8221; A driver or OS modification is more like grabbing the business end of a mace at the bottom of a trunk of swords. It&#8217;s really best to try the short sword on top of the pile first.</p><p style="text-align: right;"><strong>KV</strong></p><div><hr></div><p><strong>George V. Neville-Neil</strong> works on networking and operating system code for fun and profit. He also teaches courses on various subjects related to programming. His areas of interest are computer security, operating systems, networking, time protocols, and the care and feeding of large codebases. He is the author of <em>The Kollected Kode Vicious</em> and co-author with Marshall Kirk McKusick and Robert N. M. Watson of <em>The Design and Implementation of the FreeBSD Operating System.</em> For nearly 20 years he has been the columnist better known as Kode Vicious. Since 2014 he has been an industrial visitor at the University of Cambridge, where he is involved in several projects relating to computer security. He earned his bachelor&#8217;s degree in computer science at Northeastern University in Boston, Massachusetts, and is a member of the ACM, the Usenix Association, and IEEE. His software not only runs on Earth, but also has been deployed as part of VxWorks in NASA&#8217;s missions to Mars. He is an avid bicyclist and traveler who currently lives in New York City.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/p/smart-and-fast-thinkers-are-good?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Queue: In Practice! This post is public so feel free to share it.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/p/smart-and-fast-thinkers-are-good?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://theofficialacm.substack.com/p/smart-and-fast-thinkers-are-good?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><p></p>]]></content:encoded></item><item><title><![CDATA[Can Modern C++ Save Us?]]></title><description><![CDATA[Hardening the C++ Standard Library at massive scale]]></description><link>https://theofficialacm.substack.com/p/practical-security-in-production</link><guid isPermaLink="false">https://theofficialacm.substack.com/p/practical-security-in-production</guid><dc:creator><![CDATA[The Official ACM]]></dc:creator><pubDate>Wed, 04 Mar 2026 13:07:46 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Jx59!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Over the past few years there has been a lot of talk about memory-safety vulnerabilities, and rightly so&#8212;attackers continue to take advantage of them to achieve their objectives. Aside from security, memory unsafety can be the cause of reliability issues and is notoriously expensive to debug. Considering the billions of lines of C++ code in production today, we need to do what we can to make C++ measurably safer over the next few years with as low of an adoption barrier as possible.</p><p>In 2019, Alex Gaynor, a security expert and one of the leading voices in memory safety, wrote a piece titled &#8220;<a href="https://alexgaynor.net/2019/apr/21/modern-c++-wont-save-us/">Modern C++ Won&#8217;t Save Us</a>,&#8221; where he gave examples of foundational types such as <code>std::optional</code> that were unsafe in the idiomatic use cases. What happens when these unsafe types are used beyond their contract? Well, you guessed it: undefined behavior. The <code>std::optional</code> type isn&#8217;t the only one to behave like this. If you look at how this compares with modern languages, you can see that C++ is the outlier.</p><p>So, what&#8217;s to be done? Possibly one of the best places to start today is by improving our standard libraries. They provide the baseline &#8220;vocabulary types&#8221; for developers&#8212;<em>and if they&#8217;re not safe</em>,<em> it will be tough to build safety around them</em>. The <code>std::optional</code> type is only one of many vocabulary types in the C++ Standard Library that aren&#8217;t safe by default today. Given the current state, it seems mostly clear that the first step should be hardening our standard library, and in our case, this was LLVM&#8217;s libc++.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Jx59!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Jx59!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Jx59!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Jx59!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Jx59!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Jx59!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:3070235,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://theofficialacm.substack.com/i/186790296?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Jx59!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Jx59!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Jx59!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Jx59!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3cfd73-8ec5-42d3-a0ad-303444a08f3d_6720x4480.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>(credit: unsplash)</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://theofficialacm.substack.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h3>The Limits of Debug-Only Modes</h3><p>The idea of a <em>debug mode</em> with extra checks is not new&#8212;every major implementation of the C++ Standard Library has had one. Historically, however, they suffered from several shortcomings, notably including ABI (application binary interface) compatibility issues; but perhaps the most important shortcoming was reflected directly in its name: <code>debug</code> mode was seen as a bug-finding tool to be used in a testing environment.</p><p>There seemed to be a common sentiment reflected in other implementations of the time as well: that as long as the code is well-tested, checks in release builds were unnecessary and would introduce an unacceptable performance hit. This led to feature bloat (since performance was not a priority) and made &#8220;infeasible in release mode&#8221; a self-fulfilling prophecy.</p><p>With experience, we can confidently say that this test-only approach is not sufficient to prevent bugs in the real world. Projects with extensive test suites that make use of a multitude of bug-finding tools still suffer from costly bugs and vulnerabilities when deployed to production. Even extensive fuzzing can&#8217;t provide a complete guarantee, as high-profile vulnerabilities like the <a href="https://blog.isosceles.com/the-webp-0day/">one in libwebp</a> have demonstrated that bugs can lurk even in heavily fuzzed code. Real-world use exposes corner cases that no test suite, no matter how exhaustive, can feasibly cover&#8212;not to mention attackers with a special aptitude for finding or triggering these exact sorts of cases. Though well-intentioned, a debug-only approach ends up being of limited use during development and of no use during deployment, and, as a result, sees little adoption.</p><h3>The Case for Production Hardening</h3><p>The alternative, therefore, is to enable hardening universally in production. While testing is vital, it cannot replicate the exact conditions, subtle timings, or adversarial pressures of a live environment. Many latent bugs manifest only under production traffic or adversarial inputs. To provide safety guarantees, <em>checks must be active where the code actually runs.</em></p><p>This stance is often met with immediate skepticism based on two reasonable and deeply ingrained fears: (1) destabilizing services with crashes, and (2) unacceptable performance overhead. For hardening to be viable, both must be addressed.</p><p>First, let&#8217;s address stability. A crash from a detected memory-safety bug is not a new failure. It is the early, safe, and high-fidelity detection of a failure that was already present and silently undermining the system. The alternative to a &#8220;loud crash&#8221; is not a healthy system; it is a silently corrupted one that will fail later in a more complex, damaging, and less understandable way.</p><p>Adopting this <em>fail-stop</em> policy&#8212;terminating the process immediately upon detecting an unrecoverable memory violation&#8212;has been shown to be superior: It is more secure, makes bugs far easier to detect and fix, and ultimately leads to more reliable systems.</p><p>The second fear, performance, is equally critical. This is precisely where historical debug modes failed. Because these modes were not intended for release builds, performance was not a design constraint. Performance must be treated as a core design requirement, not an afterthought. As shown in the rest of this article, the combination of careful design and recent compiler optimization improvements made hardening affordable enough to be enabled at scale.</p><h3>Designing libc++ Hardening for Production</h3><p>The affordability of production hardening was not an accident; it was the result of a long, deliberate evolution in design. The initial push at Apple began by exploring domain-specific classes that provided improved bounds safety, but it quickly became clear that requiring code modification to migrate to nonstandard utilities lacking a rich ecosystem made adoption an uphill battle. For example, introducing a span-like class that provides improved bounds safety is a daunting task if it does not interoperate seamlessly with the plethora of algorithms provided by the standard library.</p><p>We then noticed that many C++ Standard Library data structures already had enough information to ensure bounds safety (sometimes in limited ways) and that simply hardening those accesses was the <em>constriction point</em> that would allow improving bounds safety in a large amount of existing code.</p><p>This led to successive iterations of hardening in libc++, culminating in the current design in LLVM 18, which is built on a set of core principles that make it practical for production use.</p><h4>A safety spectrum, not a switch</h4><p>Early experiences with an on/off <a href="https://prereleases.llvm.org/15.0.0/rc2/projects/libcxx/docs/UsingLibcxx.html#enabling-the-safe-libc-mode">&#8220;safe mode&#8221;</a> (introduced in LLVM 15) were encouraging. The key difference from previous debug modes was that safe mode was intended to be used in production. This imposed significant constraints on the design, as features could no longer be enabled without serious consideration of their performance impact.</p><p>As we gained experience with deployment of safe mode, new requirements surfaced. While deployment experience showed this to be a particularly good fit for some projects with adoption in Safari and Chromium, it quickly became clear that there were environments for which safe mode was too expensive. A one-size-fits-all approach is too blunt; developers need to choose the right security-versus-performance tradeoff for their environment.</p><p>The current incarnation of hardening in libc++, first released in LLVM 18, reflects this by offering four hardening modes. The two most important are intended for production:</p><p>&#8226; <code>Fast</code> mode is passionately minimalistic and enables only those hardening checks that are security-critical and can be performed with low overhead, usually in constant time; in practice, this almost exclusively means checking for out-of-bounds accesses (and thus improving spatial memory safety). It is a very lucky coincidence that some of the most valuable checks also happen to be some of the cheapest!</p><p>&#8226; <code>Extensive</code> mode enables all available library checks that can be performed with relatively low performance overhead, including those that lead to undefined behavior but aren&#8217;t security-critical.</p><p>Enabling a hardening mode is a matter of passing <a href="https://libcxx.llvm.org/Hardening.html">the right compiler flags</a> and rebuilding the application. If the application doesn&#8217;t violate library preconditions, the code should not require any changes.</p><p>The idea is that almost all applications should be able to allow <code>fast mode</code>, while more security-conscious applications might opt into <code>extensive</code> mode. Additionally, there is a <code>none</code> mode (no hardening checks&#8212;that is, the status quo) and a (new, unrelated to legacy) <code>debug</code> mode; <code>debug</code> mode contains more expensive checks, although it still aims to never affect the big-O complexity of algorithms. Each subsequent mode is a superset of the previous one, both in terms of the number of checks and the performance overhead (<code>none</code> &#8594; <code>fast</code> &#8594; <code>extensive</code> &#8594; <code>debug</code>).</p><h4>ABI compatibility, if needed</h4><p>A critical lesson from past experience is that hardening must be orthogonal to the ABI. While some attractive checks would require an ABI break (e.g., storing bounds information in iterators), tying safety to the ABI can make it unusable in many production environments. An application cannot unilaterally declare a new ABI that differs from the rest of the platform with which it must link. Platforms that can allow ABI breaks might use libc++ ABI flags that enable additional hardening checks (such as hardened iterators); when an application selects a hardening mode, it enables all checks possible in the current ABI configuration.</p><h4>Partial enablement options</h4><p>For real-world adoption, developers must be able to selectively opt out of hardening in the most performance-critical parts of their code. The practical choice is often between disabling checks for one percent of the code or not enabling hardening at all.</p><p>Thus, an important requirement for hardening in libc++ is that it can be turned on and off on a per-TU (translation unit) basis. This is achieved using Itanium ABI tags&#8212;the hardened mode that is in effect in a given TU is encoded in the tag that is attached to all library functions and affects their mangled names. Thus, a call to a vector&#8217;s subscript operator would resolve to two distinct functions if one TU calls it under <code>fast mode</code> and another under <code>none</code> mode (same for all other modes) so the ODR (One Definition Rule) is not violated.</p><h4>Efficient and customizable failures</h4><p>By default, when a check fails, libc++ terminates the program with a trap instruction, which is the most secure and lowest-overhead option. This behavior can be completely overridden by the vendor of a given platform when building the library by providing a custom header with the desired implementation of the termination handler. This is different from the weak definition approach used in safe mode. While more flexible, the previous approach resulted in binary &#8220;bloat&#8221; since the linker in the general case cannot inline the function call. In practice, most applications don&#8217;t need to override the termination handler and, in line with the general C++ principle, should not pay for what they don&#8217;t use.</p><h3>Deploying Hardening at Scale</h3><p>While a flexible design is essential, its true value is proven only by deploying it across a large and performance-critical codebase. At Google, this meant rolling out libc++ hardening across hundreds of millions of lines of C++ code, providing valuable practical insights that go beyond theoretical benefits. While hardening has also been adopted in various open-source codebases (e.g., Google Chrome, Apple&#8217;s WebKit) and in a variety of other security-critical projects at Apple, the best documented case study is that of Google&#8217;s adoption of the feature across its server-side production systems, to be discussed next.</p><h4>Phase 1: Enabling hardening in tests</h4><p>The journey to production began more than a year before the final rollout with a large-scale cleanup effort to enable hardening in pre-production builds. The first attempt to enable the checks in our unit and integration tests broke more than 1,000 tests.</p><p>Fixing this required a concerted effort, including crowdsourcing fixes from interested engineers using their 20 percent time, resulting in hundreds of patches across Google&#8217;s <a href="https://research.google/pubs/why-google-stores-billions-of-lines-of-code-in-a-single-repository/">monorepo</a>. This was essential to establish a &#8220;green&#8221; baseline, ensuring new code submitted with hardening violations would fail in CI (continuous integration), preventing backsliding.</p><p>Once the tests passed, the hardened runtime was enabled in pre-production environments (canary, staging). This allowed developers time to learn about the hardening, fix newly surfaced issues, and build confidence.</p><p>This process also drove improvements to libc++ hardening itself. For example, the original two percent binary size increase was a blocker in certain environments, so a non-verbose mode was added with a much smaller footprint, reducing the binary size overhead to less than 0.5 percent.</p><p>This phase demonstrated the sheer volume of latent issues and reinforced the necessity of the project, setting the stage for the move to production.</p><h4>Phase 2: Data-driven consensus building</h4><p>With a clean test baseline, the next hurdle was proving that production hardening was viable for a fleetwide deployment. This required performance measurement, production pilots, and consensus building.</p><p>The primary concern was performance. To address this, key services were benchmarked to understand libc++ hardening&#8217;s performance characteristics. This is where we identified that profile-guided optimization allowed us to keep hardening overhead low.</p><p>Armed with early performance data, we ran pilots with early adopters, including large, high-traffic services. Those pilots provided real-world evidence that systems remained stable and that the crashes were manageable and highly valuable for debugging. It also provided real-world performance data to estimate the cost of a fleetwide rollout, relying on <a href="https://ieeexplore.ieee.org/abstract/document/5551002/">Google&#8217;s continuous profiling infrastructure</a>.<sup>1</sup></p><p>These success stories and production data were key to building broad consensus for a default-on rollout. We made the case to Google&#8217;s engineering leadership based on four arguments:</p><p>&#8226; Demonstrated affordability of hardening</p><p>&#8226; Clear security benefits</p><p>&#8226; Immediate impact on debuggability</p><p>&#8226; Long-term improvements to reliability</p><p>Ultimately, securing buy-in across a large engineering organization was the most time-consuming phase of the project, a reflection not on the technology, but on the diligence required for a change at this scale.</p><h4>Phase 3: Production rollout</h4><p>By this point, more than 100 pilots were running in production, ranging from security-critical services to high-performance parts of the Search backend. The final phase was the full production rollout, activating hardening by default across the fleet. This began the most critical stage of the project: uncovering and fixing the latent bugs that manifest only under the unique pressures of a live production environment.</p><p>Hardened services were progressively rolled out to production, and, as expected, the safety checks began to fire. Our hypothesis was that these new deterministic crashes would not be creating new instability but, rather, mostly displacing more dangerous and opaque memory-corruption errors. Live monitoring during the rollout confirmed this theory: As the new assertion failures appeared, the baseline of segmentation fault crashes began to recede.</p><p>We staffed a centralized response to rapidly diagnose and fix underlying issues, sending hundreds of patches across our monorepo. This process purged a significant volume of latent bugs. In some rare cases, we temporarily opted out specific workloads from hardening while we worked on a fix.</p><h4>Performance</h4><p>The most significant concern&#8212;performance&#8212;proved largely unfounded in practice. Across Google&#8217;s server-side C++ codebase, the average production performance overhead of enabling libc++ hardening was measured at a remarkably low 0.3 percent.</p><p>This affordability wasn&#8217;t accidental. As Chandler Carruth, Distinguished Engineer and overall C++ language lead at Google, <a href="https://chandlerc.blog/posts/2024/11/story-time-bounds-checking/">detailed</a>, several factors likely converged:</p><p>&#8226; <em><strong>Efficient check implementation.</strong></em> The hardening checks in libc++ were carefully implemented to be lightweight.</p><p>&#8226; <em><strong>Compiler optimizations.</strong></em> Modern compilers such as Clang/LLVM became adept at optimizing checks, eliminating redundant ones within loops or proven code paths.</p><p>&#8226; <em><strong>Cross-pollination.</strong></em> LLVM&#8217;s optimization capabilities for these kinds of checks have significantly improved over the years, partly driven by the needs of memory-safe languages such as Swift and Rust, which rely heavily on runtime checks and use LLVM as a compiler backend. C++ benefited indirectly from this broader ecosystem investment.</p><p>&#8226; <em><strong>PGO</strong></em> <em><strong>(profile-guided optimization).</strong></em> This was critical. High-quality PGO data allows the compiler to identify hot paths and often move checks out of the hot paths, minimizing impact on latency-sensitive code.</p><p>We anticipated that some critical code paths would be too sensitive for any overhead. To address this, we provided two distinct escape hatches: a mechanism to opt an entire service out of hardening, and a fine-grained API to bypass checks for a specific line of code. The final tally after the rollout was remarkable. Across hundreds of millions of lines of C++ at Google, only five services opted out entirely because of reliability or performance concerns. Work is ongoing to eliminate the need for these few remaining exceptions, with the goal of reaching universal adoption.</p><p>Even more telling, the fine-grained API for unsafe access was used in just seven distinct places, all of which were surgical changes made by the security team to reclaim performance in code that was correct but difficult for the compiler to analyze. This widespread adoption stands as the strongest possible testament to the practicality of the hardening checks in real-world production environments.</p><p>While a production performance overhead of 0.3 percent is relatively small, at Google&#8217;s scale, it represents a substantial absolute cost in terms of computing resources and energy. This was a deliberate, strategic investment in improving security and reliability.</p><h4>The payoff: quantifiable impact</h4><p>&#8226; <em><strong>Bug detection.</strong></em> More than 1,000 bugs were found and fixed during the rollout, including several security vulnerabilities and bugs that had lurked in the codebase longer than a decade. Hardening is projected to prevent 1,000 to 2,000 new bugs annually at the current development velocity.</p><p>&#8226; <em><strong>Reliability.</strong></em> The baseline segmentation fault rate across the production fleet dropped by approximately 30 percent after hardening was enabled universally, indicating a significant improvement in overall stability. There was an initial uptick in crashes due to hardening checks failures, but this matched the expected hypothesis mentioned earlier; those failures would replace many segmentation faults.</p><p>&#8226; <em><strong>Security.</strong></em> Hardening demonstrably disrupted active internal offensive exercises and would have prevented others, proving its real-world effectiveness against exploitation attempts.</p><p>&#8226; <em><strong>Debuggability.</strong></em> Many subtle memory corruptions that are notoriously hard to debug were transformed into immediate, easily identifiable crashes at the point of error, saving significant developer time.</p><h3>The Path Forward</h3><p>The ultimate goal is to make these safety guarantees portable and available to all C++ developers. There is a quickly growing recognition in the C++ community that the status quo is undesirable, creating momentum for real change.</p><p>One way to push memory safety forward is to put a notion of a hardened Standard Library into the C++ Standard itself, so that developers across the board can get portable security guarantees. The initial <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3471r4.html">proposal</a> from Apple,<sup>2</sup> based on the implementation of hardening in libc++, has been recently voted into the upcoming C++26 Standard; the successful deployment experience of the hardened libc++ at Google and Apple has been crucial in getting the paper adopted.</p><p>The paper essentially standardizes a subset of libc++&#8217;s <code>fast mode</code> under the name of a <em>hardened implementation</em> that a program may choose, covering spatial memory safety in some of the most widely used standard classes, such as contiguous containers (whether a hardened or non-hardened implementation is the default is ultimately the choice of the vendor; some security-oriented platforms might choose to default to the hardened implementation). The paper is based on an observation that in fact all the hardening checks are already stated, almost always explicitly, in the Standard in the form of preconditions; it&#8217;s just that violating a precondition used to result in the dreaded undefined behavior. Changing these cases of undefined behavior into useful well-defined behavior is, from the textual point of view, quite straightforward, making the proposal a lot less disruptive than might be expected.</p><p>Follow-up papers are intended to cover any missing checks that satisfy <code>fast mode</code> criteria (security-critical and low performance overhead), and it is expected that new additions to the standard library will use hardened preconditions as appropriate to avoid OOB (out of bounds) in the hardened implementation. Modes beyond <code>fast mode</code> are not currently considered for standardization; at least for the time being, the Standard should contain only checks that almost any program can afford. There are also no plans to propose any checks that would change the ABI.</p><p>Notably, the Standard leverages another C++26 feature, Contracts, which provides an extensive framework for specifying program invariants and handling violations. That gives developers significant flexibility in how they handle a failing hardening check. Contracts <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3191r0.pdf">were designed</a> with consideration for Library Hardening as a use case, ensuring that libc++ assertion failures can be modeled directly by the Contracts evaluation semantics (specifically, the trapping mechanism used in libc++ hardening is precisely the quick-enforce evaluation semantic).</p><h3>Conclusion</h3><p>The challenge of improving the memory safety of the vast landscape of existing C++ code demands pragmatic solutions. Standard library hardening represents a powerful and practical approach, directly addressing common sources of spatial safety vulnerabilities within the foundational components used by nearly all C++ developers.</p><p>Our collective experience at Apple and Google demonstrates that significant safety gains are achievable with surprisingly minimal performance overhead in production environments. This is made possible by a combination of careful library design, modern compiler technology, and profile-guided optimization.</p><p>Rolling this out initially at a massive scale was a large undertaking. However, much of the foundational work, in both the toolchain and in uncovering issues, has now been completed. The path for other organizations to adopt hardening is now significantly clearer and less daunting.</p><p>While not a panacea and not without tradeoffs, hardening eliminates entire classes of bugs and provides a substantial return on investment for security and reliability. <em>As such, we highly recommend that any organization using C++ enable hardening in their standard library today. </em>Whether this means enabling hardening in LLVM&#8217;s libc++ or requesting a comparable safety feature from other standard library implementations, it is a critical and affordable step forward in building a more secure and reliable C++ ecosystem.</p><div><hr></div><h4>References</h4><p>1. Ren, G., Tune, E., Moseley, T., Shi, Y., Rus, S., Hundt, R. 2010. IEEE Explorer 30(4), 65&#8211;79; <a href="https://ieeexplore.ieee.org/abstract/document/5551002">https://ieeexplore.ieee.org/abstract/document/5551002</a>.</p><p>2. Varlamov, K., Dionne, L. 2025. Standard library hardening; <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3471r4.html">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3471r4.html</a>.</p><div><hr></div><p><strong>Louis Dionne</strong> works at Apple in Languages and Runtimes. He is the lead maintainer of libc++, has contributed to various security initiatives in recent years, and is an active member of the C++ Standards Committee.</p><p><strong>Alex Rebert</strong> is an engineer at Google, where he focuses on memory safety. Previously, he co-founded ForAllSecure and led the creation of Mayhem, the autonomous system that won the 2016 DARPA Cyber Grand Challenge. He was recognized by <em>MIT Technology Review</em> as one of the 35 Innovators Under 35 and by <em>Forbes&#8217;s</em> 30 Under 30.</p><p><strong>Max Shavrick</strong> is a security engineer at Google and one of the technical leads focusing on addressing memory unsafety. Before that, he worked on Windows and Azure security, finding and fixing remote code execution vulnerabilities. He was also previously president and captain of RPISEC, a student-run cybersecurity club and CTF team at Rensselaer Polytechnic Institute.</p><p><strong>Konstantin Varlamov</strong> works at Apple in Languages and Runtimes and is one of the maintainers of libc++ and a member of the C++ Standards Committee. For the past few years, his primary focus has been on the development and standardization of libc++ hardening.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/p/practical-security-in-production?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Queue: In Practice! This post is public so feel free to share it.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/p/practical-security-in-production?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://theofficialacm.substack.com/p/practical-security-in-production?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><p></p>]]></content:encoded></item><item><title><![CDATA[Is SRE Anti-Transactional?]]></title><description><![CDATA[An API for interfacing with automaters]]></description><link>https://theofficialacm.substack.com/p/is-sre-anti-transactional</link><guid isPermaLink="false">https://theofficialacm.substack.com/p/is-sre-anti-transactional</guid><dc:creator><![CDATA[The Official ACM]]></dc:creator><pubDate>Wed, 18 Feb 2026 13:07:09 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!ubtR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A major concern in the SRE movement is automation&#8212;that is, moving IT from focusing on transactional work to building systems that do work for us.</p><p>There are many competing definitions of SRE. If you ask 10 SRE engineers to define SRE, you&#8217;ll get 11 definitions. Some will focus on the <em>R</em> (reliability) as the driving force in everything from feature priorities, to budgets, to technology choices. Others use SRE as an umbrella term encompassing everything from application upkeep, cloud engineering, service provisioning, and platform engineering to nearly all aspects of keeping a technology working.</p><p>What they all have in common is an imperative to move away from transactional work. It may not be the defining attribute of the SRE domain, but it is an important aspect. Let&#8217;s drill down into it.</p><p>SREs do not like manual work. Give a team of SREs a manual process, and over time they will evolve it from fully manual (people doing work), to automated (software tools that humans use to make progress), to autonomous (systems that identify when work needs to be done, do the work, and alert humans in exceptional situations). The aim is to progress toward eliminating manual work from the system altogether.</p><p>SREs consider transactional work to be toil. Toil is work that, while valuable in and of itself, doesn&#8217;t raise the bar and improve the process for any similar future requests. It is tactical, not strategic. It addresses immediate needs rather than contributing to long-term improvements or strategic goals.</p><p>For example, deploying a new software release to a website is a good thing. The new software release has new features that benefit the user, increase profit, or otherwise provide value. In the old days, this process was done manually and would frequently require days or weeks of planning and execution. Then, the next time a new software release arrived, the same amount of work would be required to deploy it. That is <em>toil</em>.</p><p>On the other hand, a project that replaces all that manual toil with a CI/CD (continuous integration/continuous delivery or deployment) system such that developers can safely deploy new software releases in a self-service manner is <em>strategic</em>. It not only automates a manual process, thus reducing toil, but also permits the process to be done more frequently (even continuously) in smaller batches without waiting for IT to become available.</p><p>SREs gladly do manual work, but only as a necessary step of learning the process so that it can be automated and eventually become autonomous. Toil is acceptable when a task is infrequent or a process is new and ill-defined or experimental in nature. Those are exceptional situations, however.</p><p>As the old joke goes, in the future there will be a factory that needs only two employees: one human and one dog. The human&#8217;s job will be to feed the dog. The dog&#8217;s job will be to make sure nobody touches the equipment.</p><p>Once SREs rule the world, the dog will be automated as well.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ubtR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ubtR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ubtR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ubtR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ubtR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ubtR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:105885,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://theofficialacm.substack.com/i/186791470?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ubtR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ubtR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ubtR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ubtR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fceec812c-a652-4d0f-ba9b-93bbed2e43a1_1200x630.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://theofficialacm.substack.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h3>Transactional Work</h3><p>Transactional work usually takes the form of a request that&#8217;s worked on by an individual until it&#8217;s completed. Tickets opened with your IT organization are transactional work. Whether you are requesting a replacement mouse or need assistance with some technology that isn&#8217;t working correctly, the work is transactional. It begins with a request, work is performed, the requester verifies the work is complete, and then, lastly, the ticket is closed.</p><p>Transactional work is typically manual and tactical (not strategic). It addresses immediate needs rather than contributing to long-term improvements or strategic goals. It doesn&#8217;t improve the system, product, or processes in a meaningful way.</p><p>Toil scales linearly. If the number of requests increases 10x, the number of people required to complete the work increases 10x. This is unacceptable in today&#8217;s business environment. Since Ford popularized the automotive assembly line, it has become an expectation that cost should scale sublinearly with growth. That is, if 10 units of work requires 10 people, 100 units of work should require significantly fewer than 100 people.</p><p>Toil is reactive and interrupt-driven by nature, which makes planning difficult. A request arrives at an unpredictable time and requires humans to stop whatever they are doing to work on the task. Since people are not available 24x7, the requester must wait. Everyone has experienced the frustration of waiting days for someone to perform a task that takes minutes.</p><p>Automation is available 24x7, so there is less waiting.</p><p>Toil drains engineers&#8217; time and energy, preventing them from focusing on high-impact engineering work like automation, system improvement, or innovative projects. It reduces the overall efficiency and morale of the team, as engineers are bogged down in routine maintenance rather than more meaningful contributions.</p><p>Luckily, toil is usually repetitive and, thankfully, repetitive tasks often prove to offer hot opportunities for automation.</p><h3>Automation</h3><p>SREs focus on building automation that eliminates the need to do manual work. It&#8217;s not that they&#8217;re lazy; they just want to be able to scale.</p><p>Give a team of SREs a fully manual task, and over time it will go from fully manual, to automated, to autonomous. The difference between automated and autonomous is the level of automation required: Automated systems are tools that humans use to get a task done. Autonomous systems are triggered when new work arrives and they complete work on their own. With autonomous systems, the humans are there only for exceptions&#8212;edge cases that haven&#8217;t yet been automated, bugs that need to be fixed, or system optimizations.</p><p>When work is automated, it can scale super linearly. This is particularly important for Internet-based companies. As Michael O&#8217;Dell, chief scientist of the first commercial ISP, frequently said, &#8220;The only problem is scaling. All the others inherit from that one.&#8221;</p><p>The analogy we like to make is that SREs aren&#8217;t the assembly-line workers at an auto manufacturing plant. They&#8217;re the people who make the robots that make the cars.</p><p>A process generally goes through these stages:</p><p>1. <em><strong>Manual.</strong></em> Progress is made by humans doing the work, often typing or clicking, observing what results, and then making decisions about how and when to proceed.</p><p>2. <em><strong>Automated (sometimes called manual automation).</strong></em> A tool performs each step. When a task needs to be done, a human uses a tool (software) to perform that task. A single process might require many steps. SREs tend to write tools that automate those steps. Often, individual steps have bespoke tools, and the process is completed by humans who use the appropriate tool for each step, judging the results, and then deciding when to move forward to the next step.</p><p>3. <em><strong>Autonomous systems (sometimes called fully automated).</strong></em> Software initiates and executes work without human intervention. Humans are there to handle exceptions and improve the system. Once a system is stable, it&#8217;s mostly concerned with reducing the number of exceptions that require human intervention, addressing any new features and business concerns, and achieving greater efficiency.</p><p>An autonomous system is never finished. SREs live in a Sisyphean struggle: As they get closer to perfect automation, a changing world throws new toil at them. If every edge case were handled today, new business needs would appear tomorrow. If the system runs smoothly now, an underlying system will require an upgrade tomorrow.</p><p>A good system will always be a victim of its own success, becoming so popular that it exceeds its original design limits and thus requires reengineering to overcome the new bottlenecks this growth exposes. Popularity inspires new use cases, which requires redesigns and refactoring. If the system were designed to handle only green widgets, surely its success would make it attractive to the yellow-widget division. Sadly, while extending it to a new use case sounds easy, it rarely proves to be.</p><p>It&#8217;s financially impractical to automate every conceivable use case. Some use cases are so infrequent or complex that automation can offer little or no return on investment. Automating those cases would be wasteful and considered to be a bad business decision.</p><p>Thus, an autonomous system needs a team to maintain it, optimize it, and handle the exceptions. Autonomous systems are never &#8220;one and done.&#8221;</p><h3>Example: Cluster Builds</h3><p>Tom was once on a team that was deploying storage clusters. Each cluster was made up of many individual hardware and software components.</p><p>Initially, the process was manual, with hundreds of steps, each documented to varying degrees of completeness.</p><p>Soon, each phase of the process was automated; one or more tools did most of the work of each phase. It required human judgment, however, to determine whether a phase had been completed correctly or fixes were required. We relied on human judgment to determine when to start each phase. This often required checking calendars or getting a go/no-go decision from other teams.</p><p>While this situation was a great improvement over the manual process, it still required considerable human intervention to tell us when to start, what parameters were required in each instance, when to proceed to each new phase, as well as how to handle quality control. Still, it was better than a manual process in that it was more consistent, took less time, and required less cognitive load to complete each task.</p><p>The next phase was to help the system become autonomous. Orders for new clusters were no longer presented during status meetings or via tickets. Instead, orders came from a database (imagine an order received via SalesForce). A validation process not only verified the request&#8217;s parameters, but also sent an email with an approval link to the designated budget controller. Each phase then was kicked off via timetables, verification of completion of preceding steps, and other triggers.</p><p>Once the system was stable, we discovered that a typical cluster build still required human intervention at least twice during the multiday process. As we fixed edge cases, improved algorithms, and fine-tuned the system, this was reduced to nearly zero. The system had become data-driven and even had a dashboard that showed our &#8220;human intervention&#8221; count dropping over time.</p><p>This count would still spike upward occasionally. These spikes correlated with new releases of software received from the developers, since each release had a tendency to break our fussy automation. Improving this required us to break out of our silo and work more closely with the developers.</p><p>We realized that their release process needed to include verifying that the cluster-deployment system supported the new release. It was a &#8220;lightbulb moment&#8221; for the product manager when he realized the ability to deploy clusters was as much a part of a new release as the new features we had promised to ship. Maybe this is obvious in hindsight, but the authors have seen this cycle (silo, lightbulb, cooperation) repeat frequently throughout our careers.</p><p>It took more than a year to go from fully manual to an autonomous system. Most of the fine-tuning that was required after that was to scale the system both horizontally (efficiently creating larger clusters) and vertically (creating more clusters per month).</p><p>The old manual system didn&#8217;t make anyone happy. Sales recognition (which starts <em>after</em> cluster delivery) was delayed. Customers were unhappy with misconfigurations and other bugs.</p><p>The new system was fast and predictable (three days). It had an SLA that allowed the company to tell customers when to expect delivery of the service, and the sales department was alerted that a contract had to be signed three days before the end of the quarter for timely revenue recognition. Best of all, the system was autonomous, meaning orders could be fulfilled even if the SREs were asleep.</p><h3>Example: Mouse and Cable Distribution</h3><p>We used to think that one help-desk task that could never possibly be automated had to do with the procurement of small items such as replacement mice and USB cables. A customer would open a ticket requesting (for example) a mouse, whereupon the help-desk person would provide the mouse, assign the cost to the person&#8217;s department, and so on. How could that get any better?</p><p>I was impressed to discover that Google&#8217;s help desk had actually succeeded in automating that process with a vending machine for physical items. Employees could swipe their badges, take the items they desired, after which their department would be billed. This system eliminated a significant percentage of help-desk visits&#8212;meaning the toil was gone. All that was left was a management process that involved ordering new items and monitoring for abuse.</p><p>Some industry pundits claim there is a world of &#8220;old IT&#8221; that is all toil, unfixable, and doomed. We like to believe there is always hope whenever there is sufficient scale and a willingness on the part of management to embrace creativity and innovation.</p><h3>How to Interface with SREs</h3><p>Given the SRE distaste for transactional work, what&#8217;s the best way to interact with an SRE team?</p><p>Ideally, transactional requests that are manual in nature (verbal requests, tickets generated by humans, and so on) should be replaced by interactions through software. That is, your team should be able to provide an API to your SREs or request that they provide you with one. An API provides a way for the SRE software to interact with your systems and vice versa. This paves the path to automation.</p><p>Sometimes, we get lucky because an API exists. Sometimes, though, the API is obscured. For example, the database or SaaS-based product your team is using might already have an API, but access to it must be enabled, properly secured, with rules of engagement defined.</p><p>Usually, however, a new API needs to be created from scratch. This isn&#8217;t easy. There&#8217;s no magic button you can press to make an API appear. Creating an API requires the very human process of sitting down, identifying the need and requirements, proposing designs, and allocating resources to build, test, and implement that design. This usually requires software engineering skills, which not every team has available. For example, in our experience human resources departments rarely have software engineers on staff.</p><p>Efforts that mesh two teams with different levels of experience with process automation can prove to be frustrating for both teams. The non-SRE team, lacking software-development experience, can be put off by the requirement to work through a detailed process analysis given that the transactional process seems so obvious to them. The SRE team, meanwhile, can often become frustrated by the other team&#8217;s tolerance of toil and surprised at the lack of disdain for it.</p><p>If creating an API is not an option, sometimes a little creativity is all that&#8217;s required. In one case, Tom discovered that a &#8220;mostly autonomous&#8221; system was hamstrung by the fact that another team was responsible for allocating ID numbers required by the process. Basically, the process was fully autonomous apart from one &#8220;stop the world&#8221; moment that required waiting for a human on another team to allocate an ID number. This other team, meanwhile, didn&#8217;t understand the problems that resulted from this delay. Accordingly, the requests were often ignored for days. No other team made such requests and so they were viewed as &#8220;weird&#8221; and assumed to be of low priority. In reality, the delays were causing major headaches.</p><p>By sitting down and discussing the situation, the teams were able to propose two creative solutions. One was to allocate large batches of ID numbers, reducing the human interaction to just refill the ID pool&#8212;something that might happen only a few times each year. The other idea was simply to permit the SRE team to allocate ID numbers with a particular prefix, thus giving them the ability to manage their own allocation process.</p><p>Likewise, SRE teams should be willing to create interfaces for others. That could be a traditional network-based API, but often a web-based user-interface or dashboard will suffice. For example, the other team&#8217;s needs may be satisfied by gaining access to a dashboard in an existing monitoring or business information system. That could be a static webpage that&#8217;s updated periodically. And while the need to visit a webpage to find answers might smell like unacceptable toil to an SRE, a non-SRE might just as easily view it as a welcome improvement.</p><p>In the end, when we can find a way to work together to eliminate the need for tickets or to reduce toil in some other fashion, we all win.</p><h3>Conclusion</h3><p>The value of a team is its output. If the team&#8217;s role is to repeat the same task over and over again, that team&#8217;s value is going to scale linearly with their effort. But if the team&#8217;s role is to optimize processes through automation and the reduction of toil, then that team&#8217;s value will prove to be like compound interest, with growth propelling growth. SREs are happiest when they are in the latter category: creating value that scales.</p><p>Systems built by SREs are not fully autonomous on day one. It&#8217;s iteration over time that leads to fully autonomous, functional, reliable service. This iterative process requires SREs to evaluate how much time and money should be spent to achieve the objective. It is the heart of engineering to find the fastest, cheapest, and safest way to create and maintain a system.</p><p>We have seen conflicts between SRE goals and &#8220;traditional IT&#8221; mindsets. Generally, these stem from the fundamental differences between the SRE mindset of automating wherever possible to eliminate toil and the more immediate focus other teams have on completing certain specific tasks.</p><p>Understanding this tension is key to interacting with SRE teams.</p><div><hr></div><h4>Related article</h4><p>Operations and Life:<br><strong><a href="https://queue.acm.org/detail.cfm?id=2945077">The Small Batches Principle</a></strong><br>Reducing waste, encouraging experimentation, and making everyone happy<br>Thomas A. Limoncelli<br><a href="https://queue.acm.org/detail.cfm?id=2945077">https://queue.acm.org/detail.cfm?id=2945077</a></p><div><hr></div><p><strong>Thomas A. Limoncelli</strong> is a senior platform engineer at Stack Overflow Inc. He works from his home in New Jersey. His books include <em>The Practice of Cloud Administration</em> (https://the-cloud-book.com), <em>The Practice of System and Network Administration</em> (https://the-sysadmin-book.com), and <em>Time Management for System Administrators</em>. He is <a href="https://bsky.app/profile/yesthattom.bsky.social">@YesThatTom on BlueSky</a> and blogs at <a href="https://yesthatblog.com/">YesThatBlog.com</a>. He holds a B.A. in computer science from Drew University.</p><p><strong>Christian Pearce</strong> is a platform-engineering manager and a technology leader. He is a manager at Stack Overflow, leading the Infrastructure Platform Team. He focuses on building high-performing teams that focus on cloud infrastructure, developer experience, and building scalable platform solutions. He maintains a personal website at https://www.christianpearce.com and is active in the engineering community.</p><div><hr></div><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/p/is-sre-anti-transactional?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Queue: In Practice! This post is public so feel free to share it.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/p/is-sre-anti-transactional?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://theofficialacm.substack.com/p/is-sre-anti-transactional?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><p></p>]]></content:encoded></item><item><title><![CDATA[From floats to characters and back again]]></title><description><![CDATA["Is this common? Or am I missing some type of driver that would do this better?"]]></description><link>https://theofficialacm.substack.com/p/from-floats-to-characters-and-back</link><guid isPermaLink="false">https://theofficialacm.substack.com/p/from-floats-to-characters-and-back</guid><dc:creator><![CDATA[The Official ACM]]></dc:creator><pubDate>Wed, 04 Feb 2026 12:25:20 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!NEiz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Hello, you&#8217;re reading <strong>&#8220;Queue: In Practice,&#8221;</strong> a brand-new ACM newsletter series. Featuring insights from </em>ACM Queue<em>, this series is written by engineers, for engineers.</em></p><p>Queue <em>does not focus on either industry news or the latest "solutions"&#8212;it focuses on the technical challenges looming on the horizon. Each issue provides a critical look at emerging tech, highlighting the problems likely to arise and posing the tough questions that software engineers should be thinking about right now. Sharpen your thinking and stay ahead of the curve.</em></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NEiz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NEiz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png 424w, https://substackcdn.com/image/fetch/$s_!NEiz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png 848w, https://substackcdn.com/image/fetch/$s_!NEiz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png 1272w, https://substackcdn.com/image/fetch/$s_!NEiz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NEiz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png" width="1456" height="1456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:6331812,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://theofficialacm.substack.com/i/185442004?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NEiz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png 424w, https://substackcdn.com/image/fetch/$s_!NEiz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png 848w, https://substackcdn.com/image/fetch/$s_!NEiz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png 1272w, https://substackcdn.com/image/fetch/$s_!NEiz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F202ce362-e771-4e84-ad76-fe0539102fac_4000x4000.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>(credit: Art Attack)</p><h2>Driven to Distraction</h2><p>by George Neville-Neil (Kode Vicious)</p><p><strong>Dear KV,</strong></p><p>I know you have mentioned working on embedded systems in the past, and now that I have a related project, I have a question for you. The device we&#8217;re building has a lot of sensors and I&#8217;ve been slowly adding support for these to our embedded Linux kernel. Each device samples data from the environment, and they&#8217;re each a bit different, but the only common drivers that seem to match what we do are character drivers that just generate a stream of bytes. It seems strange to take a lot of floating-point data, turn it into characters, and then turn it back into floating point. Is this common? Or am I missing some type of driver that would do this better?</p><p><strong>Floating</strong></p><div><hr></div><p><strong>Dear Floating,</strong></p><p>I remember when I was preparing for my first talk years ago, people would tell me, &#8220;Start with a joke.&#8221; So, here&#8217;s one for this occasion:</p><p><em><strong>Three hardware designers go to see an OS developer.</strong></em></p><p><em><strong>The first hardware designer</strong> says, &#8220;I just developed a new device and I need a driver.&#8221;</em></p><p><em><strong>OS developer:</strong> &#8220;Sure, what does it do?&#8221;</em></p><p><em><strong>First hardware designer: </strong>&#8220;It reads GPS data and correlates it with star charts from a visible telescope.&#8221;</em></p><p><em><strong>OS developer: </strong>&#8220;You should write a character driver.&#8221;</em></p><p><strong>The second hardware designer</strong><em> says, &#8220;My new device takes temperature readings to five significant digits from across a square kilometer of ocean at depths of 1 to 100 meters.&#8221;</em></p><p><em><strong>OS developer:</strong> &#8220;Oh, so you need a character driver too.&#8221;</em></p><p><em><strong>The third hardware designer</strong> says, &#8220;My device samples quantum states throughout the known universe. It can literally see the face of god, should such exist.&#8221;</em></p><p><em><strong>OS developer:</strong> &#8220;Character driver!&#8221;</em></p><p>Alas, some jokes require a very specialized audience, but in this case I think the audience is... listening.</p><p>The thing is, once upon a time, operating systems handled many different types of data, and they did so in sometimes wildly incompatible ways. This was a problem because it meant applications had to be ported whenever a new operating system version came out or whenever someone got a new model computer.</p><p>The &#8220;everything is a byte stream, we don&#8217;t care what the format of your data is&#8221; ethos of early Unix had some very real benefits in that it allowed programs to be ported to different machines and different versions of Unix to be used with few or no changes.</p><p>But, of course, every good fairy tale also has a dark side&#8212;at least if you read the original Grimm and not that drivel that comes out of Los Angeles. And here, the problem with a simplifying assumption is that it can make for inefficient or, in your case, patently illogical software. Converting a number (which is what a computer is great at processing) into a string (which a computer is not ideally suited for) and then back to a number wastes time, memory, and CPU cycles&#8212;the very three things we&#8217;re all told never to waste in our software!</p><p>KV&#8217;s particularly favorite form of this stupidity: one of the best-known and most commonly used protocols for sending stock-ticker information does exactly this&#8212;that is, it converts numbers to strings and then back to numbers. This ridiculous scenario led finance companies to invest heavily in FPGAs (field-programmable gate arrays) just to get an edge in processing stock prices for high-frequency trading. KV was both appalled when he learned this and chagrined that he hadn&#8217;t bought stock in certain FPGA companies soon enough.</p><p>All of which is to say that sometimes, simplifying assumptions are a real problem, and sometimes, they make everything look like a nail, which then makes you think all you need is a hammer. The big challenge with modern systems is that 50 years of doing things the Unix way has left us bereft of better APIs. It&#8217;s not just the drivers but also the application APIs on top of the operating system that deal only in byte streams. It&#8217;s as if the operating system designers threw up their hands and said, &#8220;Not my job!&#8221; and left all the data interpretation to the application programmers and device developers. Since these two parties rarely, if ever, talk to each other, no real progress has been made in this area from that time until now.</p><p>So, how might we make progress? The current fad for kernel bypass libraries addresses the matter by just ignoring the operating system altogether&#8212;which, as an operating system developer myself, I can totally understand. Most days, I&#8217;d like to ignore not just the operating system but go so far as to imagine putting on elbow-length rubber gloves, grabbing the operating system, and dunking it in a 55-gallon drum of acid in order to listen to it scream and die as it dissolves (with apologies to <em>Who Framed Roger Rabbit?</em>).</p><p>But, alas, in this world outside of fantasy, we must either deal with the operating system through modification or extension, bypass it, or start over from scratch by writing a new one. This last option is the most attractive to an operating system developer, but KV doubts your employer will sign up for the associated multiyear project. But if they do, please get in touch with me!</p><p>Your most expedient but least preferable solution would be to bypass the operating system since you can write a few APIs that allow your applications to talk efficiently with the devices. Bypassing gives you the most control, the highest fidelity of data, the lowest latency of access&#8212;but all at the price of generality. That is, when you bypass the operating system, you make it so that each new program must, again, be compatible with your bypass libraries. And if you want generality back, you wind up doing what operating system developers have done forever, which is to produce generalized APIs that can be consumed by arbitrary programs. The current middle ground is to add new system calls to the operating system&#8212;a process that is fraught with peril, because modern operating systems are huge and fragile. While people do add new system calls to operating systems, this is a rare event. And, if you were to do this, you would wind up maintaining the new syscalls locally for a very long time unless you were able to convince an open-source project that your new calls were generally useful.</p><p>So, that&#8217;s where you are Make a character device driver and pay the cost of converting real data into strings, bypass the operating system, or innovate in the operating system space and produce some new system calls. I can&#8217;t say any of these choices are great. In fact, they all kind of suck in one way or another. But innovation in operating systems went out in the 1980s, and the people who are trying to bring that back now have a harder job than that crazy Greek guy rolling a rock up the hill.</p><p><strong>KV</strong></p><div><hr></div><p><strong>George V. Neville-Neil</strong> works on networking and operating system code for fun and profit. He also teaches courses on various subjects related to programming. His areas of interest are computer security, operating systems, networking, time protocols, and the care and feeding of large codebases. He is the author of <em>The Kollected Kode Vicious</em> and co-author with Marshall Kirk McKusick and Robert N. M. Watson of <em>The Design and Implementation of the FreeBSD Operating System</em>. For nearly 20 years he has been the columnist better known as Kode Vicious. Since 2014 he has been an industrial visitor at the University of Cambridge, where he is involved in several projects relating to computer security. He earned his bachelor&#8217;s degree in computer science at Northeastern University in Boston, Massachusetts, and is a member of the ACM, the Usenix Association, and IEEE. His software not only runs on Earth, but also has been deployed as part of VxWorks in NASA&#8217;s missions to Mars. He is an avid bicyclist and traveler who currently lives in New York City.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/p/from-floats-to-characters-and-back?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading! This post is public so feel free to share it.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/p/from-floats-to-characters-and-back?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://theofficialacm.substack.com/p/from-floats-to-characters-and-back?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><p></p>]]></content:encoded></item><item><title><![CDATA[If you're tired of hearing about memory safety, this article is for you]]></title><description><![CDATA[Memory Safety for Skeptics]]></description><link>https://theofficialacm.substack.com/p/if-youre-tired-of-hearing-about-memory</link><guid isPermaLink="false">https://theofficialacm.substack.com/p/if-youre-tired-of-hearing-about-memory</guid><dc:creator><![CDATA[The Official ACM]]></dc:creator><pubDate>Wed, 21 Jan 2026 12:45:31 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!pM9H!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6646612-d04c-4756-9715-1080ffd8e327_621x621.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em><strong>Happy New Year!</strong> Introducing <strong>&#8220;Queue: In Practice,&#8221;</strong> a brand-new ACM newsletter series for 2026. Featuring insights from </em>ACM Queue<em>, this series is written by engineers, for engineers.</em></p><p>Queue <em>does not focus on either industry news or the latest "solutions"&#8212;it focuses on the technical challenges looming on the horizon. Each issue provides a critical look at emerging tech, highlighting the problems likely to arise and posing the tough questions that software engineers should be thinking about right now. Sharpen your thinking and stay ahead of the curve.</em></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><p>Memory safety&#8212;the property that makes software devoid of weaknesses such as buffer overflows, double-frees, and similar issues&#8212;has been a popular topic in software communities over the past decade and has gained special prominence alongside the rise of the <a href="https://www.rust-lang.org/">Rust programming language</a>. Rust did not invent the idea of memory safety, nor was it the first memory-safe language, but it did break the dam on the last major holdout context where memory safety had not yet been achieved: what we often call &#8220;systems programming.&#8221;</p><p>Rust&#8217;s big step function was to offer memory safety at compile time through the use of static analysis borrowed and grown out of prior efforts such as <a href="https://cyclone.thelanguage.org/">Cyclone</a>, a research programming language formulated as a safe subset of C. Rust, by offering a memory-safe-by-default experience for the &#8220;systems&#8221; domain, where operating systems, databases, file systems, embedded software, and the like are made, suddenly presented a new possibility to public policymakers and to leaders of engineering organizations: the mass reduction of memory unsafety across any domain.</p><p>In the years since Rust hit the scene, tech companies have published experience reports on the adoption of Rust for production systems, whether through rewrites of existing code or by producing new modules in Rust that might have otherwise been written in C or C++. The numbers were broadly consistent: a roughly <a href="https://www.memorysafety.org/docs/memory-safety/#how-common-are-memory-safety-vulnerabilities">70 percent reduction</a> in memory-safety vulnerabilities. Rust, more than just promising memory safety, was demonstrably translating safety guarantees into practical improvements in software security. This evidence, turning the abstract benefits of a semantic improvement into bottom-line improvements in business costs (vulnerabilities are <em>expensive</em> for all involved), meant that organizations beyond just engineering groups began to take notice.</p><p>Of course, the choice of programming language is a contentious one. Languages do not exist in a vacuum, and the &#8220;right&#8221; language for a job is heavily path dependent. What languages do the developers already know? What&#8217;s the timeline and budget for the project? How serious are the correctness constraints? The performance constraints? Do you expect to hire more developers, and what resources can you allocate to train them? If you&#8217;re an open-source project, you might ask which languages would possibly bring in more developers to contribute. For any project, your answer might be determined by what other libraries or tools you will need to integrate.</p><p>What&#8217;s more, many projects have already made their programming-language decision years ago&#8212;possibly decades ago. What should they do? If the code you have today is memory unsafe, in C or C++, how can you pursue safety without throwing the whole thing out?</p><p>In some circles, the answer given might be to &#8220;rewrite it in Rust&#8221; to replace legacy software written in memory-unsafe languages with new Rust equivalents. The benefits, supporters argue, are clear: comparable performance, modern tooling, and memory safety.</p><p>Yet, experienced developers know <a href="https://blog.developer.adobe.com/we-decided-to-rewrite-our-software-you-wont-believe-what-happened-next-dd03574f6654">rewrites are expensive</a> and frequently misguided . Often, demands for large-scale rewrites are not a carefully reasoned argument about tradeoffs, but an aesthetic criticism of code that looks &#8220;ugly&#8221; or &#8220;too old.&#8221; If anything, those calling for mass rewrites show their own inability to do the difficult work of understanding and working with an existing codebase that does a job and does it well.</p><p>There are paths between accepting memory unsafety as the cost of doing business or performing a mass rewriting of stable systems in a new language to achieve safety. Reflexive rejection of a move to memory safety is misguided, especially when the benefits of memory safety can be achieved in a cost- and schedule-efficient way.</p><p>If you&#8217;re not yet sold on the value of memory safety, this article is for you. The goal in writing it is to treat the question of pursuing memory safety in legacy systems with the seriousness and rigor that it deserves.</p><p>Pursuing memory safety is worthwhile, with or without Rust, and I&#8217;d like to convince you to try.</p><div><hr></div><h3>In Budget, On Schedule</h3><p>Software systems do not exist in isolation; software is built to <em>do things</em>, to serve the needs of businesses and individuals by making systems more efficient or automatic. The development of software is constrained not by the theoretical limits of software&#8217;s abilities, but by the cost and schedule limitations of the team building it.</p><p>In <a href="https://www.cisa.gov/resources-tools/resources/case-memory-safe-roadmaps">&#8220;The Case for Memory Safe Roadmaps,&#8221;</a> a collection of government agencies from the &#8220;Five Eyes Countries&#8221; (the United States, United Kingdom, Australia, New Zealand, and Canada) collectively recommended that organizations develop roadmaps for transitioning their software development efforts to memory-safe languages.</p><p>It&#8217;s worth being clear here: Their focus is on <em>roadmaps</em>, and they very explicitly accept and discuss the challenge of the cost and schedule impacts of any transition toward memory safety.</p><p>Budget and schedule constraints and the desire for efficiency are part of what motivates the creation of software in the first place. Once that software is in place, it&#8217;s frequently mission critical, having replaced the knowledge and labor of people who would have previously done the jobs the software now performs. Instead of accountants, a company may have accounting <em>software</em>, with a smaller number of accountants who know how to interact with the software and use it to perform their own jobs built on the knowledge the software provides with its data and embedded business logic.</p><p>Rewrites to critical software systems are risky precisely because the software itself is so important. Rewriting a software system, whether as an in-place rewrite where components are swapped out piece by piece, or as a wholesale rewrite with a cutover date, <a href="https://www.theverge.com/2025/1/13/24342282/sonos-app-redesign-controversy-full-story">risks the proper functioning</a> of the business if the rewrite fails .</p><p>Complex, long-running software systems can face other severe constraints as well. They may be unable to be turned off&#8212;because, having become so business critical and time sensitive, any attempt to bring them offline for maintenance or replacement is unacceptable. They may also have become lost artifacts, where the expertise of the individuals who created them or previously worked on them is lost because it wasn&#8217;t transferred to newer engineers, resulting in a current team that does not understand the system or feel comfortable making changes to it.</p><p>There are also ongoing costs associated with the development of software that might have to be diverted to support even an incremental rewrite. Depending on the business, there might not be funding available to support an <em>increase</em> to the development team, so diversion of resources toward a rewrite would mean reduction in the delivery of features for the project, which may be untenable.</p><p>All of this is to say that rewrites, even incremental ones, are business decisions that have to be made as tradeoffs with other strategic goals. While motivated developers can make the best case possible for the upside of a rewrite, they must also grapple with the businesses&#8217; needs to deliver features and address bugs impacting users of the system today.</p><p>At the same time, a transition to memory-safe languages can bring benefits beyond just the safety (and thereby security) claims that are often given priority in these discussions.</p><p>Memory-safety violations, such as null pointer dereferences or indexing outside of the bounds of a memory buffer, can result in denial of service (or, in the context of the classic security CIA triad, availability failures) of the relevant software. This might mean on-call pages to respond to a production incident, a failure to meet service-level agreement guarantees for customers, or reduced revenue from lost customers or interruption of business operations.</p><p>Memory-safety issues are also often a central building block in a kill chain for achieving remote code execution by attackers. Even as far back as &#8220;<a href="https://archives.phrack.org/issues/49/14.txt">Smashing the Stack for Fun and Profit&#8221;</a> in 1996, we could see cybersecurity professionals documenting how to turn a buffer-overflow weakness into remote code execution and full access to the host. With that foothold in place, attackers can begin to exfiltrate data, move laterally within a network, escalate privileges, lock down a system with ransomware, conscript a host into a botnet, and more.</p><p>Software problems are <a href="https://www.sonatype.com/resources/articles/what-is-shift-left">cheaper to fix the earlier they</a> occur in the software development lifecycle. In the long term, stopping a bug from being written is cheaper than responding to a bug bounty submission or triaging a production outage.</p><p>This is not to say that <em>all</em> moves toward memory safety are cost effective or that all roadmaps for memory safety should be as aggressive as possible, but it is intended to make clear that there are both costs and savings to be had with any transition to memory safety.</p><div><hr></div><h3>Setting the Goalposts</h3><p>What is memory safety? There should be a table-stakes answer to that question to have in hand amid the push toward memory safety in public discourse, but there is not a single, fully agreed-upon, and rigorous definition. There is a new effort, announced in a recent article published in <a href="https://cacm.acm.org/opinion/it-is-time-to-standardize-principles-and-practices-for-software-memory-safety/">Communications of the ACM</a>, to develop a standard definition of memory safety, but it is just beginning.</p><p>There is, however, a rough consensus among practitioners of what kinds of program behaviors are memory <em>unsafe</em>. That&#8217;s a good place to start.</p><p>My favorite short definition <a href="http://www.pl-enthusiast.net/2014/07/21/memory-safety/">comes from Michael Hicks</a>, an academic who works on programming languages:</p><p>&#8220;[A] program execution is memory safe so long as a particular list of bad things, called <a href="http://dl.acm.org/citation.cfm?id=773473.178446">memory-access errors</a>, never occur:</p><p>&#8226; Buffer overflow</p><p>&#8226; Null pointer dereference</p><p>&#8226; Use after free</p><p>&#8226; Use of uninitialized memory</p><p>&#8226; Illegal free (of an already freed pointer, or a non-<code>malloc</code>-ed pointer)&#8221;</p><p>You will sometimes see these categories broken down further, into spatial and temporal memory safety. <em>Spatial</em> covers memory-safety issues arising from accessing locations in memory that a program should not have access to (like a buffer overflow); <em>temporal</em> covers operations on memory done in the wrong order: for example, reading memory before it is initialized, trying to free an already freed pointer, or using a pointer after it has been freed.</p><p>There&#8217;s also the CWE (Common Weakness Enumeration) category for memory-safety issues, which decomposes Hicks&#8217;s list into more granular options. CWE is a taxonomy of software weaknesses, or as CWE puts it: &#8220;condition[s] in... software... that, under certain circumstances, could contribute to the introduction of vulnerabilities.&#8221;</p><p>In <a href="https://cwe.mitre.org/data/definitions/1399.html">CWE&#8217;s memory-safety category</a>, &#8220;buffer overflow&#8221; is further broken down into six different, more-specific weaknesses, some of which are further decomposed into their own variants. This can be useful when maximum precision is warranted but is perhaps too much detail for the purposes of this article.</p><p>These definitions provide a reasonably clear picture of what constitutes memory <em>unsafety</em>. So, memory safety is when a program is guaranteed not to have those weaknesses. This can be achieved by compile-time constraints on the semantics of programs or by runtime management of memory by a garbage collector, so long as the guarantee is upheld.</p><p>This is often when perceptive onlookers will cry foul. <a href="https://doc.rust-lang.org/book/ch20-01-unsafe-rust.html">Rust permits unsafety</a>! There&#8217;s a whole unsafe keyword! How is that meaningfully different from the guarantees of C or C++?</p><p>Of course, they&#8217;re right. Rust does permit programmers to write unsafe code, but as anyone who works in safety or security will tell you, defaults matter. In fact, defaults matter a lot!</p><p>Let&#8217;s use seat belts as an example. <a href="https://magazine.northeast.aaa.com/daily/life/cars-trucks/auto-history/a-seat-belt-history-timeline/">Seat belts became generally mandatory</a> across the United States between the late 1980s to the early 1990s. In 1985, when mandatory seatbelt laws first saw passage among the states, <a href="https://crashstats.nhtsa.dot.gov/Api/Public/ViewPublication/810962#%3A~%3Atext%3D14%20percent%20in%20the%20early%2C75%20percent%20in%20another%2010">seatbelt usage sat at 21 percent</a> of riders. In 1994, the average seatbelt usage rate in the U.S. was 58 percent. As of 2017, it was <a href="https://crashstats.nhtsa.dot.gov/Api/Public/Publication/812465">89.7 percent.</a> That change in defaults led to massive increases in seatbelt usage and therefore saved more lives. The National Highway Transportation and Safety Administration estimates that in 2017 alone, <a href="https://www.nhtsa.gov/vehicle-safety/seat-belts">seatbelts saved the lives of nearly 15,000 Americans</a>.</p><p>The same truth applies in software. Before version 4.0.0 (published in 2017), Redis, the extremely popular key-value store, offered no access controls in its default configuration. Frequently, new users of Redis would unintentionally expose their instance publicly, and this insecurity would result in data spills or become a vector for host exploitation. As of version 4.0.0, Redis enters a &#8220;protected mode&#8221; when run with its default configuration and without password protection. This limits access to loopback interfaces. As the <a href="https://redis.io/blog/fewer-unsecured-redis-servers/">Redis company itself has since touted</a>, the introduction of protected mode has caused the number of publicly accessible Redis instances tracked on Shodan.io, a popular internet host aggregator, to decline substantially. In 2017, it had identified roughly 17,000 exposed Redis instances; in 2020, that number had declined to 8,000 in an audit by security company TrendMicro.</p><p>Bringing it back to memory safety, we can and should think of memory-safety guarantees by languages as a continuum, and we can split languages between &#8220;memory safe by default&#8221; and &#8220;non-memory safe by default&#8221; groups. This framing, <a href="https://memorysafety.openssf.org/memory-safety-continuum/">recommended</a> by the OpenSSF&#8217;s (Open Source Security Foundation&#8217;s) Memory Safety SIG (Special Interest Group), makes the options clearer:</p><p>&#8226; Using memory-safe-by-default languages</p><p>&#8226; Using memory-safe-by-default languages to interface with non-memory-safe-by-default languages</p><p>&#8226; Using non-memory-safe-by-default languages</p><p>Here, memory-safe-by-default languages include not only Rust, but also common garbage-collected languages such as Java, C#, Go, Swift, Python, Ruby, and more. Non-memory-safe-by-default languages include C and C++ most notably, but also Zig, which may be surprising to those who have watched memory-safety discussions from the sidelines.</p><p>While Zig does provide more ergonomic options for programmers to write memory safe programs themselves, Zig is not a memory-safe language, because it does not guarantee memory safety even in its most conservative configuration. <a href="https://www.scattered-thoughts.net/writing/how-safe-is-zig/">Jamie Brandon&#8217;s breakdown of Zig&#8217;s memory safety</a> is a good walkthrough of why Zig&#8217;s guarantees are insufficient.</p><p>With a shared understanding of memory safety and memory-safe languages, let&#8217;s now dig into the concrete strategies for pursuing memory safety in real-world programs.</p><div><hr></div><h3>Strategies for Safety</h3><p>Any of the following strategies are intended to maximize the benefit of memory safety while minimizing the cost of pursuing it. The specific choice of which approach is right is context dependent and should be made with consideration of the importance of the component, the current and new target language, the team involved, and the timetable.</p><h4>Make new code memory safe</h4><p>The first and most obvious option is to make new code memory safe&#8212;that is, to write new components in a memory-safe language. While this seems simple, you must address certain caveats to make this approach successful.</p><p>First, you are unlikely to reap the benefits of memory safety if you try introducing memory-safe code alongside new memory-unsafe code. Think of it this way: In a fixed codebase that you continue to assure (via testing, code review, bug bounties, and more), the density of vulnerabilities decreases exponentially over time. As vulnerabilities become less and less dense in the codebase, the rate of new vulnerability discoveries also decreases, and so the overall assurance level of the code <em>increases</em>. The riskiest thing you can do to a codebase is change it. In the case of memory-unsafe languages, that change can induce memory-safety vulnerabilities.</p><p>The Google Chrome and Android teams have published extensively about their experiences incentivizing a move to memory-safe languages in their codebases. They instituted a rule called the <a href="https://chromium.googlesource.com/chromium/src/%2B/master/docs/security/rule-of-2.md">&#8220;Rule of Two,&#8221;</a> where all new code must be either sandboxed or in a memory-safe language. In practice, because sandboxing is difficult, this naturally gave developers incentive to pursue memory safety in most cases.</p><p>Surprisingly to the team, <a href="https://security.googleblog.com/2024/09/eliminating-memory-safety-vulnerabilities-Android.html">they reaped the benefits of this new policy</a> across the entire codebase&#8212;even the parts that weren&#8217;t rewritten. Because they had certain assurances about the new code inherent in the safety mechanisms it came with, they could focus assurance efforts on old code, which was now static. Through this, they not only reduced the overall rate of memory-safety vulnerabilities in the codebase, but also decreased the prevalence of vulnerabilities overall.</p><h4>Target rewrites to critical components</h4><p>Sometimes, rewriting code in a memory-safe language <em>can</em> be the right choice, but this is often a path to pursue only once you fully understand the challenges faced by the current memory-unsafe code.</p><p>Early in its history, the development of Rust was funded by Mozilla, makers of the Firefox web browser, and the flagship Rust project besides Rust&#8217;s own compiler was the <a href="https://servo.org/">Servo web-rendering engine</a>. Despite this, the first actual Rust code that Mozilla integrated into Firefox was not Servo; it was <a href="https://medium.com/mozilla-tech/deploying-rust-in-a-large-codebase-7e50328074e8">an MP4 video file parser</a>. They replaced the existing C++ parser with one written in Rust, moving from a memory-unsafe language to a memory-safe language, because it had long been a source of vulnerabilities. Firefox needs to parse MP4 files from untrusted sources, and failures to correctly handle that parsing could be dire. For Mozilla, it was a small but security-critical surface area that made sense to target for a rewrite.</p><p>Another helpful tool for targeting is Kelly Shortridge&#8217;s <a href="https://kellyshortridge.com/blog/posts/the-sux-rule-for-safer-code/">SUX Rule</a>: target code that is Sandbox free, Unsafe, and eXogenous. This means you should prioritize rewriting code that processes untrusted (exogenous) input, runs without a sandbox, and is written in a memory-unsafe language. Reviewing your own codebase for these areas can be a fast way to identify critical paths with high risk of exploitation in the presence of memory-safety vulnerabilities.</p><h4>Wrap unsafe code with safe interfaces</h4><p>When fully rewriting existing memory-unsafe code to a memory-safe language is not feasible, it might instead make sense to wrap it in a memory-safe interface. This does still lay the burden of ensuring safety properties on the programmer, both for the original code in the memory-unsafe language and for the correctness of the interface, but it then permits building safe and trusted new code on top of the old code. If you continue to work to assure the old code with techniques such as fuzz testing, analysis by sanitizers, or formal modeling, you can gain increased confidence in the latent unsafe code being wrapped.</p><p>This is in fact how many of the Rust standard library&#8217;s <a href="https://doc.rust-lang.org/nomicon/vec/vec.html">common container types are written</a>. Under the hood, they contain unsafe code to manage buffers and pointers in a way that is as efficient as possible, but the interface provided to the user does not give access to any materials (buffers, pointers, lengths) that would permit the user to violate memory-safety guarantees.</p><p>This &#8220;wrapping&#8221; approach helps constrain the &#8220;blast radius&#8221; of memory-unsafe code that can&#8217;t feasibly be removed or replaced and constrains the auditing scope and assurance costs of that code as well.</p><h4>&#8220;Get good&#8221; is not a strategy</h4><p>There is a common reply in conversations about memory safety, coming from the most hardcore skeptics: Programmers should just write better code. They argue, explicitly or implicitly, that programmers who benefit from the guardrails of memory safety are <em>bad programmers</em>, and that <em>real programmers</em> are sufficiently skilled that they do not need a machine double-checking their work.</p><p>Let&#8217;s be clear: This is anti-intellectual nonsense&#8212;macho self-aggrandizement masquerading as a serious technical argument. You should not take it seriously and should consider someone advancing this argument as fundamentally unserious and to be ignored.</p><p>There is no step function in quality of work in the history of human achievement that happened because people one day woke up and decided to be better at their jobs. Improvements in productivity or quality or reductions in error and harm happen because of the invention of new techniques, processes, and tools.</p><p>Reductions in traffic fatalities in the 1980s and 1990s didn&#8217;t happen because drivers suddenly got better at driving; they happened because states enacted mandatory seat-belt laws.</p><p>While individuals <em>can</em> become more skilled at their jobs, working faster or producing fewer errors, <em>large groups</em> of people generally don&#8217;t do so without some force that works to provide incentive or enable that change. Even when improvements are nontechnical, they come from enhancements to process or incentives for behavior. Over the past several decades, hospitals, for example, have reduced in-hospital mistakes because of increased use of standard checklists and provisioning of common materials needed for emergencies in crash carts.</p><p>Programmers who argue against memory safety by arguing for mass self-improvement are posing an impossible future as an alternative against a credible opportunity for improvements in software safety and security. While there are credible case-specific arguments against individual paths to memory safety, they do not include sudden mass improvement of skill and quality across the industry. It&#8217;s important to make this clear.</p><div><hr></div><h3>Regulations and Requirements</h3><h4>No, governments are not banning C or C++</h4><p>One specter of the conversations around memory safety is whether the use of memory-unsafe languages will become generally unacceptable, either through formal government regulation or a rise in common requirements for software purchasing.</p><p>Today no agency, either in the U.S. or outside of it, regulates against the use of languages that are non-memory safe by default. Nor are there purchasing requirements in place calling for the use of memory-safe-by-default languages or even the presence of memory-safety roadmaps, at least for governments.</p><p>The Five Eyes report mentioned previously, &#8220;The Case for Memory Safe Roadmaps,&#8221; <em>recommends</em> that organizations establish roadmaps for the pursuit of memory safety, but this is nonregulatory, and no amendments have been made to federal software acquisition policy to require such a roadmap in the U.S. or elsewhere. The U.S. is not outlawing C or C++. While these agencies have recommended moving away from these languages for future software development, they have not recommended indiscriminate mass rewrites of existing code.</p><p>Also note that the processes for establishing regulation or requirements would face challenges and, whether successful or not, would be slow to take effect and offer ample time for feedback and consideration.</p><p>First, regarding the prospect of regulation around memory safety in the U.S., such regulation would need to be pursued by a relevant agency that can establish a relevant jurisdiction. With <a href="https://www.lawfaremedia.org/article/lawfare-daily--the-supreme-court-takes-the-bait--loper-bright-and-the-future-of-chevron-deference">the end of Chevron deference in U.S. law</a>, a requirement that judges defer to U.S. regulatory agencies&#8217; determinations in most cases that was abolished in 2024 by the U.S. Supreme Court in <em>Loper Bright Enterprises v. Raimondo</em>, this pursuit of memory-safety regulation would also likely need to be explicitly backstopped by Congressional mandate to ensure it survived legal challenges where judges may overrule agency rulemaking.</p><p>Second, regarding <em>acquisition requirements</em> (the federal government&#8217;s term for the rules around purchasing done by the government), the <a href="https://www.acquisition.gov/browse/index/far">FAR (Federal Acquisition Regulation)</a> would need to be updated to incorporate requirements for memory safety. For reference, in 2020 President Biden signed <a href="https://bidenwhitehouse.archives.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/">Executive Order 14028</a>, which included a request that federal agencies pursue an amendment to the FAR to require inclusion of an SBOM (software bill of materials) for all software purchased by the federal government. To date, those changes have not been made, and no such requirement is in place within the FAR.</p><p>This is not to say that regulation or future federal purchasing requirements are impossible, but simply to point out that none are in place today, and any such changes would take time to be enacted and implemented.</p><p>The U.S. government&#8217;s role around memory safety has so far been to act as cheerleader and promoter of the idea, including with the Office of the National Cyber Director&#8217;s report, <a href="https://bidenwhitehouse.archives.gov/oncd/briefing-room/2024/02/26/press-release-technical-report/">&#8220;Future Software Should Be Memory Safe;&#8221;</a> CISA (Cybersecurity and Infrastructure Security Agency) et. al.&#8217;s &#8220;Case for Memory Safe Roadmaps;&#8221; and CISA&#8217;s inclusion of memory-safety recommendations within its <a href="https://www.cisa.gov/securebydesign">Secure by Design</a> effort to collaborate with industry on improving software security.</p><h4>Governments do not need to ban C or C++</h4><p>Even without government mandate, many organizations in the tech industry have publicly stated their support for pursuing memory safety. In 2023, the <a href="https://bidenwhitehouse.archives.gov/oncd/briefing-room/2024/08/09/fact-sheet-biden-harris-administration-releases-end-of-year-report-on-open-source-software-security-initiative-2/">Office of the National</a> Cyber Director put out an RFI (request for information) seeking advice from the public on how best to support improving the security of open-source software. That RFI included an interest in the possibility of promoting adoption of memory-safe languages in open source.</p><p>Respondents to the RFI, which includes a number of universities, think tanks, corporations, and individuals, overwhelmingly supported a move toward memory safety. Few espoused a hardline goal of rewriting all existing code from non-memory-safe languages, but many did recognize the value of pursuing memory safety in new code, and in rewriting critical components in security-sensitive contexts when possible.</p><p>Some companies, <a href="https://security.googleblog.com/2024/03/secure-by-design-googles-perspective-on.html">most notably Google</a>, have been especially vocal about their experiences with the value of memory safety. To them, the promise of memory safety is a reduction in security-related costs for long-term products such as the Google Chrome web browser or the Android operating system. By reducing memory-safety vulnerabilities at the source, they shift vulnerability costs left in the software development life cycle; the cost of catching a bug during development and stopping it from being shipped at all is orders of magnitude cheaper than the cost of receiving a security report, perhaps paying out a bug bounty, and then coordinating, preparing, and releasing a patch.</p><p>In some corners there has been a paranoia and fear that recommendations around memory safety from the U.S. government and others portend some forced end to C or C++. Bjarne Stroustrup, originator of C++ and continued major participant in the ISO Working Group that maintains the C++ specification, has <a href="https://www.theregister.com/2025/03/02/c_creator_calls_for_action/">recently begun to sound alarm bells</a> in papers and speeches about the existential threat posed to C++ by failing to address the demands for memory safety, with clear reference to the possibility that software written in non-memory-safe-by-default languages may be disallowed or become practically untenable to market and sell in the future.</p><p>This fear is simultaneously overblown and correct. It is overblown to suggest the U.S. or any other government is close to outlawing C or C++, but it is correct to note that the benefits of memory safety are becoming clearer with each case study performed at scale and that we should expect natural incentives to slowly accrue larger use and developer interest in memory-safe languages over non-memory-safe languages. C and C++ won&#8217;t die, but they will likely decline and become legacy languages like Cobol or Ada. They will still sustain some degree of interest and community, and a smaller number of developers will likely continue to be able to make their careers as developers in these languages, but they will be languages that present developers with fewer labor-market opportunities in the future and are unlikely to ascend in popularity and use again without substantial changes to address these safety deficiencies.</p><div><hr></div><h3>Safety Is Worth Pursuing</h3><p>Memory-safe languages present the clearest opportunity today to substantially improve software security. While memory safety does not eliminate all classes of software weaknesses, it does eliminate a particularly pernicious class that leads to disproportionately severe vulnerabilities. While there are other techniques for addressing these kinds of weaknesses (for example, hardware-based approaches such as CHERI), they are less mature and generally more difficult to adopt at scale.</p><p>The state of possibility with memory safety today is similar to the state of automobile safety just prior to the widespread adoption of mandatory seat-belt laws. As car manufacturers began to integrate seat belts as a standard feature across their model lines and states began to require that drivers wear seat belts while driving, the rate of traffic fatalities and severity of traffic-related injuries dropped drastically. Seat belts did not solve automobile safety, but they credibly improved it, and at remarkably low cost.</p><p>The same can be done with memory safety. There is an opportunity to make substantial inroads at addressing a serious class of vulnerabilities while also, long-term, saving money on the development and operation of software systems. Memory safety is not a silver bullet, but it is a credible and cost-effective assurance technique that we as an industry should pursue aggressively. We do not need to wait for regulation to catch up; it is in our best interests to act today.</p><div><hr></div><p><strong>Andrew Lilley Brinker</strong> is a principal engineer at MITRE, where he works on software security. He contributes to the CVE Quality Working Group, serves on the OmniBOR Core Team, and leads development of Hipcheck. He lives in southern California with his wife and two dogs.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/p/if-youre-tired-of-hearing-about-memory?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading! This post is public so feel free to share it.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://theofficialacm.substack.com/p/if-youre-tired-of-hearing-about-memory?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://theofficialacm.substack.com/p/if-youre-tired-of-hearing-about-memory?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><p></p>]]></content:encoded></item></channel></rss>