Skip to content

Archive

Software Engineering

462 articles
Software Engineering 19 Sep 2026 6 min read

Write Skew Breaks Cross-Row Invariants Under Snapshot Isolation

Snapshot isolation can let two transactions commit even when their combined result violates a rule that each transaction checked before writing. The anomaly appears when both transactions read the same logical condition, then write different rows. Because their write sets do not overlap, ordinary write-write conflict detection has nothing to reject. This is write skew. It matters at the boundary between application invariants and database isolation: a transaction may see a consistent snapshot and still participate in a final state that would have failed its own predicate.

Software Engineering 19 Sep 2026 5 min read

Version Columns Turn Database Updates into Conditional State Transitions

A database client can read a row, spend time computing a change, then issue an UPDATE after another transaction has already changed the same row. If the final statement identifies the row only by its primary key, the later write can replace state derived from the intervening transaction without any visible conflict. A version column changes that boundary. The client reads both the application state and a revision value, then includes that revision in the update predicate. The database accepts the write only while the stored revision still matches the state the client observed.

Software Engineering 19 Sep 2026 8 min read

Transactional Outbox Couples State Change to Message Intent

A service that updates its database and publishes an event to a message broker crosses two independent commit boundaries. If the database commit succeeds and the broker publish fails, durable state exists without its corresponding message. Reversing the order only reverses the failure: a consumer can observe a message for a state change that never commits. A transactional outbox narrows this gap by placing the application write and a durable message record in the same local database transaction. Publication moves to a separate relay. The pattern does not make the database and broker one atomic system; it changes the boundary so message intent becomes part of the database commit.

Software Engineering 19 Sep 2026 7 min read

Sequence Counters Detect Concurrent Writes Without Reader Locks

A sequence counter can let readers copy shared state without taking the writer’s lock. The reader samples a counter, copies the protected fields, then samples the counter again. A stable even value at both observations indicates that no writer overlapped the copy under the synchronization contract. A changed or odd value forces the reader to discard the snapshot and retry. This pattern moves work away from reader-side lock ownership, but it does not remove synchronization. Writers still need serialization, counter transitions need defined memory-ordering semantics, and the protected data must remain safe to access during an overlapping write. Those constraints make sequence counters suitable for some read-mostly snapshots and unsafe for data whose lifetime can disappear beneath a reader.

Software Engineering 19 Sep 2026 6 min read

seccomp User Notification Moves Selected Syscall Decisions to a Broker

A seccomp filter can do more than allow or reject a system call immediately. With user notification, a matching call can be suspended while another process receives a structured request on a listener file descriptor and decides what result the blocked thread receives. The mechanism turns selected syscall decisions into a brokered interface without moving the entire syscall implementation into user space. The boundary is precise but narrower than a general interposition layer. The kernel still owns syscall dispatch, task state, descriptor tables, and validation performed by kernel code. The broker receives metadata and can return a value, an error, or in supported cases request continued execution of the original syscall. Correct designs account for mutable target memory, notification lifetime, and the fact that a policy decision is not automatically a transaction over process state.

Software Engineering 19 Sep 2026 6 min read

Request Coalescing Collapses Concurrent Cache Misses into One Fill

A cache can reduce steady-state backend traffic yet amplify work at the instant a popular entry expires. If one hundred requests observe the same missing key before any replacement value is stored, a conventional lookup path can send one hundred equivalent reads to the origin. The cache is functioning according to its lookup rules; the amplification comes from concurrency around the empty interval. Request coalescing changes that interval. The first caller for a key starts the fill, while later callers for the same key attach to that in-flight operation instead of starting equivalent work. When the operation completes, its result is distributed to the waiting callers and, when appropriate, stored in the cache.

Software Engineering 19 Sep 2026 5 min read

process_vm_readv and process_vm_writev Transfer Memory Across Process Boundaries

process_vm_readv() and process_vm_writev() let one Linux process copy bytes directly between its address space and another process’s address space. The calls operate on vectors of local and remote memory ranges, but a successful process lookup does not make remote memory stable. Mapping changes, page accessibility, permissions, and concurrent mutation remain separate parts of the contract. These interfaces are Linux-specific system calls. They do not define C object lifetime, synchronization, or a portable interprocess-memory model.

Linux 19 Sep 2026 6 min read

process_madvise Applies Memory Advice Across Process Boundaries

A process can consume memory on behalf of work that is coordinated elsewhere. Linux process_madvise() lets that external coordinator apply selected virtual-memory advice to ranges in the target process without injecting code into it. The target is identified by a pidfd, while the ranges are supplied as an array of struct iovec. That arrangement separates memory-policy decisions from the code that owns the mapping. A runtime manager, service supervisor, or memory controller can request reclaim-oriented or prefetch-oriented treatment for another process, subject to kernel support and permission checks. The system call does not transfer ownership of the mapping, freeze the target, or make its address space stable.

Linux 19 Sep 2026 6 min read

pidfd_getfd Duplicates a Live Descriptor Across Process Boundaries

A process can acquire a new descriptor that refers to the same open file description as a descriptor already held by another process, without asking that target process to send it. Linux provides this operation through pidfd_getfd(). The resulting descriptor is local to the caller, but the kernel object behind it is shared with the target descriptor. That distinction matters because a descriptor number is only an entry in one process’s descriptor table. The open file description carries state such as the current file offset and file status flags. Duplicating across a process boundary therefore transfers access to an existing kernel file instance rather than reopening the pathname or constructing an independent instance.

Linux 19 Sep 2026 6 min read

PAGEMAP_SCAN Batches Page-Table State into Address Ranges

A large virtual address range may contain only a small number of page-state transitions. Reading one pagemap entry for every virtual page exposes that state at page granularity, but it also makes user space inspect a long sequence of entries. Linux PAGEMAP_SCAN moves the filtering into the kernel and reports matching spans as struct page_region records. The interface is an ioctl() on /proc/PID/pagemap. A request supplies an address interval, category predicates, a return mask, and an output vector. The kernel walks page tables and emits contiguous regions whose selected page properties match the request. This changes the shape of page-table inspection from a stream of per-page values into a filtered range query.

Software Engineering 19 Sep 2026 8 min read

Open File Description Locks Bind Byte Ranges to File Instances

A byte-range lock can protect the same inode yet have radically different lifetime semantics depending on what owns the lock. Traditional fcntl() record locks are process-associated. Open file description locks instead attach to the kernel open file description referenced by a descriptor. That shift changes which close operation releases a lock, what survives fork(), and whether two threads in one process can contend on the same file region. Linux exposes this model through F_OFD_SETLK, F_OFD_SETLKW, and F_OFD_GETLK. The range model remains familiar: struct flock specifies a read lock, write lock, or unlock together with an offset and length. The significant difference is ownership.

Software Engineering 19 Sep 2026 8 min read

MQTT and QUIC Solve Different Parts of a Chat Transport

MQTT and QUIC Solve Different Parts of a Chat Transport MQTT and QUIC are often placed in the same comparison table when discussing real-time chat. That comparison is convenient, but it collapses two different protocol layers into one choice. MQTT is an application-layer messaging protocol. It defines concepts such as clients, brokers, topics, subscriptions, retained messages, session state, and delivery quality of service. QUIC is a secure transport protocol over UDP. It provides connections, streams, flow control, loss recovery, encryption, and connection migration mechanisms.

Software Engineering 19 Sep 2026 5 min read

LLVM Poison Values Defer Undefined Behavior Through the IR

LLVM IR does not turn every invalid arithmetic or pointer condition into immediate undefined behavior. Many instructions produce a poison value instead. That value can flow through later instructions, preserving the optimizer’s ability to rely on promises such as “this addition does not overflow” without forcing undefined behavior at the exact instruction where the promise is violated. This is part of LLVM’s semantics, not an optimizer implementation detail. A frontend that emits nsw, nuw, inbounds, noundef, or related constraints is stating facts that later passes may trust.

Software Engineering 19 Sep 2026 6 min read

Linux pidfds Bind Process Operations to Stable Kernel References

A numeric process ID names a process only while that PID remains assigned to it. After process exit and reaping, Linux may reuse the number for another process. Code that observes a PID, performs unrelated work, then acts on that number can therefore cross a lifetime boundary that the integer itself does not encode. Linux pidfds provide a file-descriptor reference to a process so later operations can target the referenced process object rather than repeat a numeric PID lookup.

Software Engineering 19 Sep 2026 6 min read

Linux membarrier Moves Memory Ordering Cost to a Coordinating Thread

A concurrent runtime can have thousands of fast-path operations for every rare state transition that requires global coordination. Placing a full memory barrier on every fast path makes each operation pay for that rare transition. Linux membarrier() supports the opposite arrangement: a coordinating thread enters the kernel and forces a defined ordering point across a target set of threads, moving more cost to the infrequent side of the protocol. This is not a generic replacement for atomics, mutexes, or language memory models. It is a Linux kernel interface whose guarantees apply to memory accesses and targeted threads under specific commands. Correct use requires a protocol that already defines which accesses occur before and after the coordination point.

Software Engineering 19 Sep 2026 6 min read

io_uring Linked Requests Encode Dependency in Submission Order

An io_uring submission queue can contain many operations at once, but not every operation has to be independent. Setting IOSQE_IO_LINK on a submission queue entry binds it to the next entry, forming a chain in which execution order and failure propagation become part of the kernel-visible request structure. That changes the contract compared with submitting two unrelated SQEs and coordinating them after completion. A linked chain expresses dependency before the kernel starts processing the operations. The distinction matters when a later request is valid only after an earlier request has completed, or when failure of one stage should prevent the remaining stages from running.

Linux 19 Sep 2026 6 min read

Idmapped Mounts Remap Ownership Without Rewriting Inodes

The same inode can appear with different ownership through two mount points without any recursive chown(). Linux idmapped mounts attach an ID mapping to a mount, so VFS ownership presentation and permission checks can translate user and group IDs for that view while the ownership stored by the filesystem remains unchanged. This property separates persistent inode metadata from the identity view exposed at a particular mount. It is especially useful when a filesystem tree must be shared with a container whose user namespace maps IDs differently from the host.

Software Engineering 19 Sep 2026 6 min read

Idempotency Keys Bound Retry Safety to a Request Identity

A client can send the same logical operation more than once even when it intended one effect. A timeout after POST /payments leaves an ambiguous boundary: the server may have committed the payment while the client received no response. Retrying restores delivery, but an ordinary retry can create a second payment. An idempotency key changes the interface by giving repeated attempts a stable request identity. The key is not a substitute for transactionality, and it does not make every operation intrinsically idempotent. It creates a protocol between client and server: attempts carrying the same key are treated as candidates for the same logical operation. The server still needs rules for request equivalence, concurrent arrival, persistence lifetime, failure recovery, and response replay.

Software Engineering 19 Sep 2026 7 min read

Idempotency Keys Bind Retries to One Logical Mutation

A client can lose an HTTP response after the server has committed the requested mutation. From the client’s perspective, the operation is unresolved: the connection failed, but that failure does not reveal whether durable state changed. Retrying the same POST can then create a second order, payment attempt, reservation, or other mutation. An idempotency key gives the retry a stable identity that is separate from any single transport attempt. The server can associate repeated requests carrying that identity with one logical operation. That mechanism narrows an ambiguity at the API boundary, but the key alone is not a guarantee. Its scope, persistence, request comparison, concurrency control, and replay policy determine what repeated delivery actually means.

Software Engineering 19 Sep 2026 7 min read

How Language Runtimes Use CPU Cores: Threads, Goroutines, Workers, and Processes

A CPU with many cores does not make application code parallel by itself. The operating system can schedule multiple threads at the same time, but the language and runtime decide how application work reaches those threads. That distinction explains why Go, Rust, C++, Java, JavaScript, and PHP can all use a multicore machine even though their programming models look very different. The useful question is not simply whether a language is “multithreaded.” It is how a unit of application work becomes something the operating system can schedule.

Software Engineering 19 Sep 2026 5 min read

How GitHub Codespaces Uses Core-Hours, Port Forwarding, and CI

A GitHub Codespace is a development machine running in the cloud, not a CI runner with an editor attached. It stays interactive while a developer edits files, runs commands, starts servers, debugs processes, and commits changes. That distinction explains three behaviors that are easy to confuse: how compute quota is measured, how localhost becomes reachable from a browser, and where CI begins after code is pushed. Core-hours measure machine capacity multiplied by active time Codespaces compute usage is measured in core-hours. The accounting model is straightforward:

Software Engineering 19 Sep 2026 6 min read

Generation Counters Keep Reused Handles Bound to the Right Resource

A compact handle often looks like an integer because an integer is cheap to store, copy, compare, and pass across an API boundary. In a table-backed resource manager, that integer may simply be an index into a slot array. The representation works until a slot is released and later reused. An old handle can then point at a new resource that happens to occupy the same index. The failure is not an out-of-bounds access. The index can be perfectly valid. The problem is identity: the handle names a storage location, while the caller treats it as the identity of the resource that once occupied that location.

Software Engineering 19 Sep 2026 6 min read

Fencing Tokens Reject Stale Writers After Lease Expiry

A distributed lease can transfer ownership without stopping the process that previously held it. A worker may pause long enough for its lease to expire, then resume after another worker has acquired the same lease. At that point both processes can execute code that was written under the assumption of exclusive ownership. Lease expiry settles ownership in the coordination service. It does not revoke CPU time, cancel an in-flight network request, or erase buffered I/O on the former holder. Fencing tokens address that gap by carrying an ordering value from the ownership decision to the resource being protected.

Software Engineering 19 Sep 2026 6 min read

Fencing Tokens Close the Stale Lease Writer Gap

A distributed lease can expire while its holder is unable to run. The holder may later resume with local state that still says it owns the lease, even though another client has already acquired a newer lease. If the protected storage or service accepts operations solely because the client once acquired the lease, two clients can mutate the same resource across different points in time. A fencing token moves the decisive check from lease ownership into the protected resource. Each successful acquisition receives a token ordered after every earlier token. The resource records the greatest accepted token and rejects operations carrying an older value. The lease still coordinates acquisition, but the token constrains what a delayed former holder can do after it resumes.