More from Notes on software development
There are a few interesting scenarios to keep in mind when writing applications (not just databases!) that interact with read and writes files, particularly in transactional contexts where you actually care about the integrity of the data and when you are editing data in place (versus copy-on-write for example). If I don't say otherwise I'm talking about behavior on Linux. The research version of this blog post is Parity Lost and Parity Regained and Characteristics, Impact, and Tolerance of Partial Disk Failures. These two papers also go into the frequency of some of the issues discussed here. These behaviors actually happen in real life! Thank you to Alex Miller and George Xanthakis for reviewing a draft of this post. Terminology Some of these terms are reused in different contexts, and sometimes they are reused because they effectively mean the same thing in a certain configuration. But I'll try to be explicit to avoid confusion. Sector The smallest amount of data that can be read and written atomically by hardware. It used to be 512 bytes, but on modern disks it is often 4KiB. There doesn't seem to be any safe assumption you can make about sector size, despite file system defaults (see below). You must check your disks to know. Block (filesystem/kernel view) Typically set to the sector size since only this block size is atomic. The default in ext4 is 4KiB. Page (kernel view) A disk block that is in memory. Any reads/writes less than the size of a block will read the entire block into kernel memory even if less than that amount is sent back to userland. Page (database/application view) The smallest amount of data the system (database, application, etc.) chooses to act on, when it's read or written or held in memory. The page size is some multiple of the filesystem/kernel block size (including the multiple being 1). SQLite's default page size is 4KiB. MySQL's default page size is 16KiB. Postgres's default page size is 8KiB. Things that go wrong The data didn't reach disk By default, file writes succeed when the data is copied into kernel memory (buffered IO). The man page for write(2) says: A successful return from write() does not make any guarantee that data has been committed to disk. On some filesystems, including NFS, it does not even guarantee that space has successfully been reserved for the data. In this case, some errors might be delayed until a future write(), fsync(2), or even close(2). The only way to be sure is to call fsync(2) after you are done writing all your data. If you don't call fsync on Linux the data isn't necessarily durably on disk, and if the system crashes or restarts before the disk writes the data to non-volatile storage, you may lose data. With O_DIRECT, file writes succeed when the data is copied to at least the disk cache. Alternatively you could open the file with O_DIRECT|O_SYNC (or O_DIRECT|O_DSYNC) and forgo fsync calls. fsync on macOS is a no-op. If you're confused, read Userland Disk I/O. Postgres, SQLite, MongoDB, MySQL fsync data before considering a transaction successful by default. RocksDB does not. The data was fsynced but fsync failed fsync isn't guaranteed to succeed. And when it fails you can't tell which write failed. It may not even be a failure of a write to a file that your process opened: Ideally, the kernel would report errors only on file descriptions on which writes were done that subsequently failed to be written back. The generic pagecache infrastructure does not track the file descriptions that have dirtied each individual page however, so determining which file descriptors should get back an error is not possible. Instead, the generic writeback error tracking infrastructure in the kernel settles for reporting errors to fsync on all file descriptions that were open at the time that the error occurred. In a situation with multiple writers, all of them will get back an error on a subsequent fsync, even if all of the writes done through that particular file descriptor succeeded (or even if there were no writes on that file descriptor at all). Don't be 2018-era Postgres. The only way to have known which exact write failed would be to open the file with O_DIRECT|O_SYNC (or O_DIRECT|O_DSYNC), though this is not the only way to handle fsync failures. The data was corrupted If you don't checksum your data on write and check the checksum on read (as well as periodic scrubbing a la ZFS) you will never be aware if and when the data gets corrupted and you will have to restore (who knows how far back in time) from backups if and when you notice. ZFS, MongoDB (WiredTiger), MySQL (InnoDB), and RocksDB checksum data by default. Postgres and SQLite do not (though databases created from Postgres 18+ will). You should probably turn on checksums on any system that supports it, regardless of the default. The data was partially written Only when the page size you write = block size of your filesystem = sector size of your disk is a write guaranteed to be atomic. If you need to write multiple sectors of data atomically there is the risk that some sectors are written and then the system crashes or restarts. This is called torn writes or torn pages. Postgres, SQLite, and MySQL (InnoDB) handle torn writes. Torn writes are by definition not relevant to immutable storage systems like RocksDB (and other LSM Tree or Copy-on-Write systems like MongoDB (WiredTiger)) unless writes (that update metadata) span sectors. If your file system duplicates all writes like MySQL (InnoDB) does (like you can with data=journal in ext4) you may also not have to worry about torn writes. On the other hand, this amplifies writes 2x. The data didn't reach disk, part 2 Sometimes fsync succeeds but the data isn't actually on disk because the disk is lying. These are called lost writes or phantom writes. You can be resilient to phantom writes by always reading back what you wrote (expensive) or versioning what you wrote. Databases and file systems generally do not seem to handle this situation. The data was written to the wrong place, read from the wrong place If you aren't including where data is supposed to be on disk as part of the checksum or page itself, you risk being unaware that you wrote data to the wrong place or that you read from the wrong place. This is called misdirected writes/reads. Databases and file systems generally do not seem to handle this situation. Further reading In increasing levels of paranoia (laudatory) follow ZFS, Andrea and Remzi Arpaci-Dusseau, and TigerBeetle.
This is an external post of mine. Click here if you are not redirected.
Last month I completed my first year at EnterpriseDB. I'm on the team that built and maintains pglogical and who, over the years, contributed a good chunk of the logical replication functionality that exists in community Postgres. Most of my work, our work, is in C and Rust with tests in Perl and Python. Our focus these days is a descendant of pglogical called Postgres Distributed which supports replicating DDL, tunable consistency across the cluster, etc. This post is about how I got here. Black boxes I was a web developer from 2014-2021†. I wrote JavaScript and HTML and CSS and whatever server-side language: Python or Go or PHP. I was a hands-on engineering manager from 2017-2021. I was pretty clueless about databases and indeed database knowledge was not a serious part of any interview I did. Throughout that time (2014-2021) I wanted to move my career forward as quickly as possible so I spent much of my free time doing educational projects and writing about them on this blog (or previous incarnations of it). I learned how to write primitive HTTP servers, how to write little parsers and interpreters and compilers. It was a virtuous cycle because the internet (Hacker News anyway) liked reading these posts and I wanted to learn how the black boxes worked. But I shied away from data structures and algorithms (DSA) because they seemed complicated and useless to the work that I did. That is, until 2020 when an inbox page I built started loading more and more slowly as the inbox grew. My coworker pointed me at Use The Index, Luke and the DSA scales fell from my eyes. I wanted to understand this new black box so I built a little in-memory SQL database with support for indexes. I'm a college dropout so even while I was interested in compilers and interpreters earlier in my career I never dreamed I could get a job working on them. Only geniuses and PhDs did that work and I was neither. The idea of working on a database felt the same. However, I could work on little database side projects like I had done before on other topics, so I did. Or a series of explorations of Raft implementations, others' and my own. Startups From 2021-2023 I tried to start a company and when that didn't pan out I joined TigerBeetle as a cofounder to work on marketing and community. It was during this time I started the Software Internals Discord and /r/databasedevelopment which have since kind of exploded in popularity among professionals and academics in database and distributed systems. TigerBeetle was my first job at a database company, and while I contributed bits of code I was not a developer there. It was a way into the space. And indeed it was an incredible learning experience both on the cofounder side and on the database side. I wrote articles with King and Joran that helped teach and affirm for myself the basics of databases and consensus-based distributed systems. Holding out When I left TigerBeetle in 2023 I was still not sure if I could get a job as an actual database developer. My network had exploded since 2021 (when I started my own company that didn't pan out) so I had no trouble getting referrals at database companies. But my background kept leading hiring managers to suggest putting me on cloud teams doing orchestration in Go around a database rather than working on the database itself. I was unhappy with this type-casting so I held out while unemployed and continued to write posts and host virtual hackweeks messing with Postgres and MySQL. I started the first incarnation of the Software Internals Book Club during this time, reading Designing Data Intensive Applications with 5-10 other developers in Bryant Park. During this time I also started the NYC Systems Coffee Club. Postgres After about four months of searching I ended up with three good offers, all to do C and Rust development on Postgres (extensions) as an individual contributor. Working on extensions might sound like the definition of not-sexy, but Postgres APIs are so loosely abstracted it's really as if you're working on Postgres itself. You can mess with almost anything in Postgres so you have to be very aware of what you're doing. And when you can't mess with something in Postgres because an API doesn't yet exist, companies have the tendency to just fork Postgres so they can. (This tendency isn't specific to Postgres, almost every open-source database company seems to have a long-running internal fork or two of the database.) EnterpriseDB Two of the three offers were from early-stage startups and after more than 3 years being part of the earliest stages of startups I was happy for a break. But the third offer was from one of the biggest contributors to Postgres, a 20-year old company called EnterpriseDB. (You can probably come up with different rankings of companies using different metrics so I'm only saying EnterpriseDB is one of the biggest contributors.) It seemed like the best place to be to learn a lot and contribute something meaningful. My coworkers are a mix of Postgres veterans (people who contributed the WAL to Postgres, who contributed MVCC to Postgres, who contributed logical decoding and logical replication, who contributed parallel queries; the list goes on and on) but also my developer-coworkers are people who started at EnterpriseDB on technical support, or who were previously Postgres administrators. It's quite a mix. Relatively few geniuses or PhDs, despite what I used to think, but they certainly work hard and have hard-earned experience. Anyway, I've now been working at EnterpriseDB for over a year so I wanted to share this retrospective. I also wanted to cover what it's like coming from engineering management and founding companies to going back to being an individual contributor. (Spoiler: incredibly enjoyable.) But it has been hard enough to make myself write this much so I'm calling it a day. :) I wrote a post about the winding path I took from web developer to database developer over 10 years. pic.twitter.com/tf8bUDRzjV — Phil Eaton (@eatonphil) February 15, 2025 † From 2011-2014 I also did contract web development but this was part-time while I was in school.
I have the fortune to review a few important blog posts every year and the biggest value I add is to call out sentences or sections that make no sense. It is quite simple and you can do it too. Without clarity only those at your company in marketing and sales (whose job it is to work with what they get) will give you the courtesy of a cursory read and a like on LinkedIn. This is all that most corporate writing achieves. It is the norm and it is understandable. But if you want to reach an audience beyond those folks, you have to make sure you're not writing nonsense. And you, as reviewer and editor, have the chance to call out nonsense if you can get yourself to recognize it. Immune to nonsense But especially when editing blog posts at work, it is easy to gloss over things that make no sense because we are so constantly bombarded by things that make no sense. Maybe it's buzzwords or cliches, or simply lack of rapport. We become immune to nonsense. And even worse, without care, as we become more experienced, we become more fearful to say "I have no idea what you are talking about". We're afraid to look incompetent by admitting our confusion. This fear is understandable, but is itself stupid. And I will trust you to deal with this on your own. Read it out loud So as you review a post, read it out loud to yourself. And if you find yourself saying "what on earth are you talking about", add that as a comment as gently as you feel you should. It is not offensive to say this (depending on how you say it). It is surely the case that the author did not know they were making no sense. It is worse to not mention your confusion and allow the author to look like an idiot or a bore. Once you can call out what does not make sense to you, then read the post again and consider what would not make sense to someone without the context you have. Someone outside your company. Of course you need to make assumptions about the audience to a degree. It is likely your customers or prospects you have in mind. Not your friends or family. With the audience you have in mind, would what you're reading make any sense? Has the author given sufficient background or introduced relevant concepts before bringing up something new? Again this is a second step though. The first step is to make sure that the post makes sense to you. In almost every draft I read, at my company or not, there is something that does not make sense to me. Do two paragraphs need to be reordered because the first one accidentally depended on information mentioned in the second? Are you making ambiguous use of pronouns? And so on. In closing Clarity on its own will put you in the 99th percentile of writing. Beyond that it definitely still matters if you are compelling and original and whatnot. But too often it seems we focus on being exciting rather than being clear. But it doesn't matter if you've got something exciting if it makes no sense to your reader. This sounds like mundane guidance, but I have reviewed many posts that were reviewed by other people and no one else called out nonsense. I feel compelled to mention how important it is. Wrote a new post on the most important, and perhaps least done, thing you can do while reviewing a blog post: edit for clarity. pic.twitter.com/ODblOUzB3g — Phil Eaton (@eatonphil) January 29, 2025
More in technology
It's time to treat Trump like the crisis he is
Here's hoping this post is short and sweet… Back in 2019 I moved my blog off of WordPress and over to Ghost. In short, I wasn't happy with WordPress and wanted a blogging engine that felt more like it was made for blogging than a
This week, I sampled one of the world’s great spiritual texts: the Qur’an. I also read poems by Rumi and saw a movie that led me to question my understanding of both. Readings As with many other people in the West, my understanding of Islam mostly comes from the news — often, in negative light. Also, I was raised Catholic and can’t help but parse these teachings through that tradition. Which is to say, I tried to read objectively, but aware that I’m likely biased. That said, I relished the opportunity to experience this book firsthand. The Qur’an has an interesting structure. Like many other books, it’s divided into chapters (surahs.) But instead of a chronological or topical organization, chapters are roughly sequenced from longest to shortest. (Except the first, which is a short prayer.) Gioia recommended fifteen surahs. As I often do after reading classic texts, I asked ChatGPT for a summary. Here it is verbatim: 1. Al-Fatiha (The Opening): A short prayer for guidance, mercy, and the straight path. Central to every unit of Muslim prayer. 2. Al-Baqara (The Cow): Longest surah; covers law, ethics, worship, community life, and stories of earlier prophets. Establishes Islam’s moral and legal foundations. 3. Al-Imran (The Family of Imran): Addresses Christians and Jews, emphasizes the unity of divine messages, and recounts the stories of Mary and Jesus with warnings against disbelief. 4. An-Nisa (The Women): Focuses on justice, women’s rights, inheritance laws, and proper conduct in war and peace; warns against hypocrisy and betrayal. 5. Al-Ma’ida (The Table Spread): Deals with dietary laws, contracts, and relations with Jews and Christians. Emphasizes loyalty to God’s covenant and the finality of Muhammad’s message. 12. Yusuf (Joseph): A narrative surah telling the story of Joseph in a literary and emotional style. A tale of patience, betrayal, forgiveness, and divine providence. 17. Al-Isra (The Night Journey): Takes its name from Muhammad’s mystical journey to Jerusalem and heaven. Emphasizes the Qur’an’s authority and the consequences of moral choices. 18. Al-Kahf (The Cave): Contains allegorical stories (Sleepers of the Cave, Moses and the Wise Man, Dhul-Qarnayn) about faith, knowledge, and the trials of life. 32. As-Sajda (The Prostration): Stresses the importance of divine revelation and resurrection. Calls for humility and recognition of God’s signs in creation. 36. Ya-Sin: Considered the “heart of the Qur’an”; focuses on God’s power, the resurrection, and human accountability, often recited for the dying. 55. Ar-Rahman (The Most Merciful): A poetic celebration of God’s mercy, creation, and judgment—famous for the refrain: “Which of your Lord’s favors will you deny?” 67. Al-Mulk (The Sovereignty): Reflects on God’s dominion over life and death. Encourages awe and contemplation of the natural world as a sign of divine power. 103. Al-Asr (Time): A short, stark reminder that time is running out—success lies in faith, good works, truth, and patience. 112. Al-Ikhlas (Sincerity): A concise declaration of pure monotheism: God is one, eternal, without equal or offspring. As may be evident here, the Qur’an blends spiritual teachings with social instruction, proposing norms, values, and institutions for a society centered on God. If Christianity’s core message is love, the core here is belief — specifically, belief in one supreme God. All else falls in line behind that idea. Reading Rumi deepened my understanding and appreciation. Through his poems, I perceived signals of what it might be like to live in a world saturated with God: ecstasy at the sight of a flower or the moon’s reflection in a still pond. Still, he reminds us these are only words: This is how it always is A great silence overcomes me, Gioia recommended a selection of Rumi’s poems, but I’ve enjoyed them enough that I’ve decided to read a whole collection. Rather than speedruning through it, I’ll read a bit at a time during my morning journaling sessions throughout the rest of the year. Audiovisual Music: Nusrat Fateh Ali Khan plus music from Tunisia. I was familiar with Ali Khan; his music was everywhere in the 1990s. He’s also one of the performers in the LAST TEMPTATION OF CHRIST soundtracks I highlighted earlier this year. Revisiting his music now gave me a new appreciation; like Rumi, he seems to express the ecstasy of living in a world soaked in divinity. Art: Gioia recommended looking at Islamic architecture. I’ve had the privilege of visiting two of the world’s great Islamic buildings, Hagia Sophia in Istanbul and the Alhambra in Granada. So that’s where my mind went. Hagia Sophia is one of the most impressive spaces I’ve ever been in; it must be experienced firsthand. That said, this NOVA program explains the building’s historical, cultural, and structural significance: This short presentation helped me understand the spiritual significance of sequencing and structure in Islamic religious buildings: The Alhambra is impressive for different reasons. For one thing, it’s not a religious structure. It’s arguably most famous for its beautiful mosaics. This video focuses on the palace’s hydraulic network, one of the world’s great engineering feats: This TEDEd presentation helped me understand the significance of the astonishing geometric decorations in these buildings: Both of these buildings also highlight Islam’s complex relationship with Christianity. Hagia Sophia started as a Christian church before being converted into a mosque, and the Alhambra stands as a reminder that part of Europe was under Islamic rule for a time. Cinema: rather than selecting a movie related to this week’s readings, I chose one I’d wanted to watch for a long time: Hal Ashby’s 1979 satire BEING THERE, starring the great Peter Sellers. By chance, a sheltered, single-minded, TV-obsessed, illiterate gardener named Chance is unwittingly thrust into the highest echelons of economic and political power. Due to his genteel demeanor, his naive utterances are continually misinterpreted as profundities. He remains aloof and uninvolved even as he becomes incredibly powerful. Rather, he becomes powerful because he is aloof and uninvolved. He has no awareness of (or concern for) how his words are interpreted, so he remains cool and neutral. This amplifies his image as a sage, feeding his growing myth. He and his interlocutors live in diverging worlds, reading into each others’ utterances meanings that aren’t there. Reflections Or are they? The movie suggests words don’t have inherent meaning; the meaning is in how we interpret them. Context informs understanding. Lacking an official backstory, people parse Chance through their preconceptions. In the first act, he introduces himself as “Chance the gardener.” But the idea that this seemingly refined gentleman is a mere gardener seems so unlikely that his interlocutor misinterprets his name as the more upper class Chancey Gardiner. And so it remains. When Chance(y) says “I like to watch,” he means something very different than what others hear, leading to particular and often unexpected actions. And it’s actions that ultimately matter. The Talmud puts it succinctly: “We do not see things as they are, we see them as we are.” I think about this whenever I engage with ancient scriptures. These texts were produced by and for very different cultures. The words mean different things to me than they likely meant to their original audiences. It’s not just that they were written in a language I don’t understand: they were written in a world I don’t understand. And yet, they endure. Why? We make the meaning. More precisely: meaning emerges as we parse the text through our particular understandings. And meaning adds value to our lives. What I took from my reading is that Islam positions itself as the culmination of monotheism. Characters, stories, and themes from the Jewish and Christian scriptures are present here too, but with a different focus. Somewhere along the line, Judaism and Christianity softened on the idea that there’s only one God. Islam aims to correct course. The idea of single-mindedly centering your life on something other than yourself is appealing. (Post-Freud, we’d say ego is the enemy.) The concept isn’t unique to Islam, of course. (And again, I’m likely reading into it.) What seems different is the Qur’an’s confident assertion of its message’s universal relevance. I can see how this all-encompassing vision can be seen as incompatible with secular post-modern societies. The Abrahamic traditions are also closely related, which can foster mutual understanding but also intensify disagreement. But I also sense the conflict emerges from literal readings, which we shouldn’t do. Again, these words emerge from — and speak to — different contexts. And I see the transcendent beauty in Rumi’s poems, the patterns of the Alhambra, and Nusrat Fateh Ali Khan’s singing, much as I do in Chartres Cathedral, the Mass in B Minor, and the Divine Comedy. All remind me that words can connect people to higher orders of being and to each other, elevating us all. Does God come in through the words or through what we bring to the words? Does it matter? It does. As Nietzsche warned, once we lose sense of the words’ specialness, we approach them differently — much like Chancey’s friends would hear him differently if they knew he was mere Chance. Some might say truth is what ultimately matters: that Chance is just a gardener who is, in the words of a character who knows, “stuffed with rice pudding between th’ ears. Shortchanged by the Lord, and dumb as a jackass.” But another character who also knows opts to not reveal the “truth” to avoid destroying his dying friend’s comforting illusion. An act of mercy? Delusion? Both? And then there’s the film’s last shot, which I won’t spoil. Let’s just say it casts doubts on whether any of these characters — or us voyeurs in this world of Chance — really knows what is in front of our eyes. Notes on Note-taking I used ChatGPT more extensively this week than at any previous point in the course. I started a ChatGPT project with the following system prompt: You are an expert tutor in literature, history, music, cinema, and more – in short, the humanities. I am in a year-long program to read through (and listen to and watch) the most important humanities works from across the world. You’ll provide summaries, pointers, and advice. Respond concisely but helpfully. Whenever possible, contextualize content by pointing out possible parallels with the modern day. Within this context, I asked ChatGPT to bring perspective to what I was reading — especially some of the most difficult passages and parallels between the other two Abrahamic traditions. I found parts of surah 4 challenging — especially those that address warfare and justice. I asked ChatGPT for a charitable interpretation of the scripture, and the LLM helpfully responded with explanations that helped me understand the text in its broader context. ChatGPT didn’t recommend it, but this video from Bishop Robert Barron also reminded me that the Judeo-Christian scriptures also have similarly difficult passages and that we must interpret them in the context for which they were written: After watching the TEDEd video about geometry in Islamic architecture, I asked ChatGPT, “How does the repetition through tessellation evident in Islamic decoration reflect the religion’s spiritual values?” I’ll quote its answer verbatim, since I found it both insightful and exemplary of the value I’m getting from using AI in this way: Beautiful question—and one that gets at the visual theology of Islam. Islamic decoration, especially through geometric tessellation, is not just ornamental—it’s deeply expressive of spiritual truths. Here’s how repetition, pattern, and abstraction in Islamic art reflect the core values of the faith: ⸻ 1. Unity in Multiplicity (Tawhid) The oneness of God (tawhid) is Islam’s central belief. Repeating geometric patterns express how divine unity underlies all diversity—a single pattern unfolds into infinite forms, just as all creation reflects the One. Spiritual message: Beneath complexity lies a single divine source. ⸻ 2. Infinity and the Transcendent Tessellations can theoretically extend forever—they have no beginning or end. This evokes infinity, a symbol of God’s eternal, boundless nature. The viewer is drawn into a contemplative state by the endless repetition. Spiritual message: God is beyond time, form, and limit. ⸻ 3. Non-figurative, Non-idolatrous Representation Islamic tradition discourages figural imagery in sacred contexts to avoid idolatry. Abstract, geometric art avoids representing God and instead points toward Him by evoking beauty, harmony, and transcendence. Spiritual message: God cannot be pictured—but can be reflected in patterns of perfection. ⸻ 4. Contemplation and Remembrance (Dhikr) Like repeated prayer or names of God, visual repetition becomes a form of remembrance. Islamic art invites stillness, reflection, and mental surrender—a visual dhikr. Spiritual message: Still the ego, contemplate the divine, dissolve into the pattern. ⸻ 5. Mathematics as Sacred Language Islamic artists used advanced geometry and symmetry, often guided by spiritual cosmology. The precision of the art mirrors the divine order in the cosmos, hinting that the universe is intelligible, ordered, and meaningful. Spiritual message: Creation is a sign (ayah) pointing to its Creator. The LLM included a helpful table: Artistic Feature Spiritual Reflection Repetition / Tessellation Unity, infinity, divine order No images of God or people Transcendence, anti-idolatry Symmetry and precision Balance, harmony, divine perfection Infinite extension God’s boundlessness and eternal presence Meditative patterning Encourages contemplation and surrender It concluded: Islamic art, in this sense, functions like visual theology: it doesn’t depict the divine, but invites you to perceive it—not through representation, but through pattern, balance, and beauty. Would you like to see some examples or diagrams that illustrate how these patterns are constructed mathematically or spiritually? I was intrigued by this last question, especially given that OpenAI just released improved ChatGPT image rendering capabilities. So I responded, “Yes, please show me an example diagram that illustrates these principles.” At this point, ChatGPT generated this image: Up Next We’re moving into the second quarter of the course. Gioia recommends books 1 and 2 of the Aeneid, book 1 of Ovid’s Metamorphoses, and a few other Roman poems, aphorisms, and proverbs. So we’re on our way back to Rome! Again, there’s a YouTube playlist for the videos I’m sharing here. I’m also sharing these posts via Substack if you’d like to subscribe and comment. See you next week!
Nick Timiraos for the Wall Street Journal: Corporate America’s Euphoria Over Trump’s ‘Golden Age’ Is Giving Way to Distress Investors were caught flat-footed by Trump’s animus toward Canada, which wasn’t a part of last year’s election campaign. Global
US bridges at risk of ship collisions, Airbus testing an unducted fan, an earthquake in Myanmar, China’s undersea cable cutter, and more.