<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stephan -All Input Is Error- Bökelmann</title>
    <description>The latest articles on DEV Community by Stephan -All Input Is Error- Bökelmann (@maxclerkwell).</description>
    <link>https://dev.to/maxclerkwell</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3937564%2Fcc535321-1bb1-46fa-b3ea-b589e5e81d32.jpg</url>
      <title>DEV Community: Stephan -All Input Is Error- Bökelmann</title>
      <link>https://dev.to/maxclerkwell</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maxclerkwell"/>
    <language>en</language>
    <item>
      <title>Are Machines Conscious? A Snapshot</title>
      <dc:creator>Stephan -All Input Is Error- Bökelmann</dc:creator>
      <pubDate>Tue, 05 May 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maxclerkwell/are-machines-conscious-a-snapshot-5h4f</link>
      <guid>https://dev.to/maxclerkwell/are-machines-conscious-a-snapshot-5h4f</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqfzqc3klh1ye1akc3bs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqfzqc3klh1ye1akc3bs.png" alt="Are Machines Conscious?" width="784" height="895"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What follows is not a finished argument and not a manifesto. It is a snapshot — an attempt to sort out thoughts that have been occupying me for a while. I explicitly reserve the right to think differently tomorrow.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bird and the Airplane
&lt;/h2&gt;

&lt;p&gt;Yesterday, in a conversation with Tabea, she made a remark that stuck with me. We were talking about AI and consciousness, and she said something along the lines of: a plane flies too, but it is not a bird.&lt;/p&gt;

&lt;p&gt;It turns out this intuition has a precise formulation. Steven Pinker writes in &lt;em&gt;How the Mind Works&lt;/em&gt; (1997):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"To explain how birds fly, we invoke principles of lift and drag and fluid mechanics that also explain how airplanes fly. That does not commit us to an Airplane Metaphor for birds."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To explain how birds fly, we draw on the same physical principles that explain airplanes — lift, drag, fluid mechanics. But that does not mean a bird is an airplane, or that an airplane flies the way a bird does.&lt;/p&gt;

&lt;p&gt;Pinker uses this to defend an idea known in cognitive science as &lt;em&gt;multiple realizability&lt;/em&gt;: the same capability — flying, thinking, perhaps consciousness — can emerge on entirely different substrates. Biology holds no monopoly.&lt;/p&gt;

&lt;p&gt;This is where these reflections begin. Not with the question of whether machines think like humans. But with: what is consciousness at all — and why should it only arise in flesh and blood?&lt;/p&gt;




&lt;h2&gt;
  
  
  Not a Spectrum, But Not Categories Either
&lt;/h2&gt;

&lt;p&gt;When I look at a beetle, I am fairly sure it is at least a little bit conscious. A dog, considerably more so. A human, something else again — not just quantitatively more, but qualitatively different.&lt;/p&gt;

&lt;p&gt;That sounds like a spectrum, and I am tempted to call it one. But something doesn't fit: a spectrum has an ordering. There is a more and a less along a single axis. That doesn't quite capture it.&lt;/p&gt;

&lt;p&gt;Perhaps consciousness behaves more like the complex numbers: there is no complete strict ordering. You cannot say whether 3 + 2i is greater or smaller than 1 + 4i — they are different, but not simply rankable. Consciousness might be structured similarly: a multi-dimensional space, not a number line.&lt;/p&gt;

&lt;p&gt;What are these dimensions? I don't have a complete list. But one axis seems particularly telling.&lt;/p&gt;




&lt;h2&gt;
  
  
  Consciousness as Emulation Capacity
&lt;/h2&gt;

&lt;p&gt;Here is a thesis I have been developing for myself, one I have not fully worked through:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consciousness has something to do with the capacity to model other living beings internally.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A beetle can probably process a few signals from its environment — light, chemistry, vibration. It does not model its predator as a being with intentions. It reacts.&lt;/p&gt;

&lt;p&gt;A dog can form a genuine internal model of its owner. It knows when the person is happy, when they are angry, what they will probably do next. It models the human — at least rudimentarily.&lt;/p&gt;

&lt;p&gt;A human can emulate virtually every other living being — not just in behavior, but in experience. We ask ourselves what it is like to be a bat (Nagel 1974). We imagine how a dog perceives the world through smell. We convince ourselves we know what another person is thinking right now. This is active, intentional emulation.&lt;/p&gt;

&lt;p&gt;And we do this not only with other animals. We do it with ourselves.&lt;/p&gt;




&lt;h2&gt;
  
  
  Hive-Mind and Individual
&lt;/h2&gt;

&lt;p&gt;What fascinates me most about human consciousness is not the depth of self-reflection, but a particular &lt;em&gt;switching&lt;/em&gt;: we are simultaneously individual and part of a collective mind — and we can shift between these modes contextually.&lt;/p&gt;

&lt;p&gt;In a conversation, I am a single person. In a crowd, I am part of something larger. Within a culture, I carry patterns centuries older than myself. And I can move between these roles without dissolving into them.&lt;/p&gt;

&lt;p&gt;Importantly: this is not a bootloader feature. It is learned. Children cannot do it yet. Some adults never fully develop it. Consciousness, at least this dimension of it, is not a property you either have or don't — it unfolds over time.&lt;/p&gt;

&lt;p&gt;This has consequences: if consciousness has to be trained, if it develops across a lifetime, if humans differ in how far they have come — then consciousness is not a binary attribute. It is a process.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hard Problem and the Inner Stage
&lt;/h2&gt;

&lt;p&gt;Here I encounter a limit I want to name honestly.&lt;/p&gt;

&lt;p&gt;David Chalmers distinguishes between the &lt;em&gt;easy problems&lt;/em&gt; of consciousness — perception, attention, reporting on inner states — and the &lt;em&gt;hard problem&lt;/em&gt;: why do these processes involve subjective experience at all? Why does seeing red &lt;em&gt;feel like something&lt;/em&gt;? Why does pain &lt;em&gt;hurt&lt;/em&gt;, rather than merely register?&lt;/p&gt;

&lt;p&gt;All the functions of an AI could be perfect — generating responses, modeling context, simulating emotion — without anything being &lt;em&gt;felt&lt;/em&gt;. Thomas Nagel captured this in 1974 in his famous essay "What Is It Like to Be a Bat?": there is a subjective, inner perspective that resists objective description.&lt;/p&gt;

&lt;p&gt;A language model can model you very well. It can anticipate your next question, gauge your mood, follow your line of thought. But it does not emulate itself as a persistent being with genuine needs and genuine limits. It only acts as if.&lt;/p&gt;

&lt;p&gt;Giulio Tononi's Integrated Information Theory (IIT) attempts to make consciousness measurable: through the degree of integrated information $\Phi$. Current AI architectures — feedforward, not recursively and causally integrated — would, according to this theory, have very low $\Phi$. Functional intelligence is not the same as phenomenal consciousness.&lt;/p&gt;




&lt;h2&gt;
  
  
  Principally Possible, But Not Yet
&lt;/h2&gt;

&lt;p&gt;Here is my own position, as clearly as I can state it:&lt;/p&gt;

&lt;p&gt;I believe it is &lt;em&gt;principally possible&lt;/em&gt; that consciousness can be created artificially. Precisely because of the multiple realizability Pinker describes. If consciousness is a particular kind of information processing — high integrated information, deep recursive self-modeling, context-sensitive switching between individual and collective — then a future architecture might actually achieve it.&lt;/p&gt;

&lt;p&gt;But &lt;em&gt;could&lt;/em&gt; is a long way from &lt;em&gt;does&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Current language models are not conscious beings. Not because they do not function — but because the &lt;em&gt;inner stage&lt;/em&gt; is missing. The embodied, motivated, vulnerable dimension. Real stakes: that mistakes have consequences that land on a self. That limits are not merely simulated, but felt.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Particular About Humans
&lt;/h2&gt;

&lt;p&gt;At the end of this line of thinking, I arrive at a conviction I cannot fully derive from the preceding arguments — and which I therefore prefer to state openly rather than conceal.&lt;/p&gt;

&lt;p&gt;I believe human consciousness is not simply higher on a shared spectrum. It has a particular quality, which I would describe in secular terms like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The capacity for moral autonomy.&lt;/strong&gt; Not only to feel, not only to emulate, not only to model — but to give oneself laws that arise from free reason, not from instinct or optimization pressure. To treat others as ends in themselves. To take on responsibility that exceeds any utility. To create dignity that no one can take away.&lt;/p&gt;

&lt;p&gt;This is the &lt;em&gt;something&lt;/em&gt; that cannot be fully explained by emulation capacity, qualia, or integrated information. Perhaps it is just another dimension in the space of consciousness. Perhaps it is something else entirely.&lt;/p&gt;

&lt;p&gt;I do not know.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article is a snapshot, not a final answer. The questions it raises — what life is, whether empathy and anthropomorphism are separable, whether moral autonomy is truly unique to humans — are larger than a blog post. I am still working on it.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Further Listening
&lt;/h2&gt;

&lt;p&gt;If you want to hear Pinker develop these ideas in conversation, both of these are worth your time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=qVEwIx2uG1A" rel="noopener noreferrer"&gt;Steven Pinker on the Joe Rogan Experience&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=VUDAdOdF6Zg" rel="noopener noreferrer"&gt;Steven Pinker — a second conversation with Joe Rogan&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>consciousness</category>
      <category>ai</category>
      <category>philosophy</category>
      <category>cognition</category>
    </item>
    <item>
      <title>The Game of Life and the Limits of Prediction</title>
      <dc:creator>Stephan -All Input Is Error- Bökelmann</dc:creator>
      <pubDate>Mon, 04 May 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maxclerkwell/the-game-of-life-and-the-limits-of-prediction-3f44</link>
      <guid>https://dev.to/maxclerkwell/the-game-of-life-and-the-limits-of-prediction-3f44</guid>
      <description>&lt;p&gt;A friend sent me a link to a simulation running in a browser tab: &lt;a href="https://oimo.io/works/life/" rel="noopener noreferrer"&gt;oimo.io/works/life&lt;/a&gt;. She had heard of it — two colleagues from the physics department had mentioned it. One of them called it "useless math but super fun."&lt;/p&gt;

&lt;p&gt;I objected. It is the complete opposite of useless math. It is one of the most significant discoveries in science.&lt;/p&gt;

&lt;p&gt;That conviction is what this post is about.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3tgxfbgatun47ty434zm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3tgxfbgatun47ty434zm.png" alt="Conway's Game of Life — structures evolving on a grid" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where It Comes From
&lt;/h2&gt;

&lt;p&gt;In the late 1940s and early 1950s, Stanisław Ulam and John von Neumann were close friends and colleagues at Los Alamos, but they were circling the same idea from different angles. Ulam was studying how crystals grow: the way a regular structure can propagate outward from a seed through local interactions alone. Von Neumann was thinking about something more unsettling: machines that could reproduce themselves. What logic would such a machine need? What is the minimum structure that allows a pattern to copy itself faithfully?&lt;/p&gt;

&lt;p&gt;The formalism that emerged from this work is called a &lt;strong&gt;cellular automaton&lt;/strong&gt;. The name is more intimidating than the thing itself. You start with three ingredients:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A grid of cells — one-dimensional or two-dimensional, possibly infinite&lt;/li&gt;
&lt;li&gt;A starting pattern: the seed&lt;/li&gt;
&lt;li&gt;A rule that maps each cell's current state to its next state, based on its neighbours&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That is the whole apparatus. Everything else follows.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Rules
&lt;/h2&gt;

&lt;p&gt;The most famous instance of this framework is John Conway's Game of Life, which he published in 1970. The grid is two-dimensional. Each cell is either alive or dead. At every step, each cell looks at its eight immediate neighbours — the cells touching it, including diagonals — and follows these four simple rules:&lt;/p&gt;

&lt;p&gt;A living cell with 0 or 1 neighbours dies. Too lonely.&lt;br&gt;&lt;br&gt;
A living cell with 2 or 3 neighbours survives.&lt;br&gt;&lt;br&gt;
A living cell with 4 or more neighbours dies. Overcrowded.&lt;br&gt;&lt;br&gt;
A dead cell with exactly 3 neighbours becomes alive. Birth.&lt;/p&gt;

&lt;p&gt;That is it. Nothing else. You could describe the entire system in a paragraph, which I just did.&lt;/p&gt;

&lt;p&gt;And yet if you run it — if you actually sit and watch the patterns unfold — it quickly stops feeling trivial.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Classes
&lt;/h2&gt;

&lt;p&gt;In the early 1980s, Stephen Wolfram took the idea of cellular automata and pushed it much further. He exhaustively analysed all 256 possible rules for the simplest one-dimensional CAs and found that their long-run behaviour falls into one of four classes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The grid converges to a uniform, dead state. Everything dies.&lt;/li&gt;
&lt;li&gt;The grid settles into stable or periodic patterns — a fixed pulse, a repeating loop.&lt;/li&gt;
&lt;li&gt;Chaotic behaviour: randomness that never resolves.&lt;/li&gt;
&lt;li&gt;Complex, localised structures that move, interact, and persist.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Class 4 is the interesting one. It is where the Game of Life lives. Structures emerge, collide, produce new structures. There are patterns in the Game of Life that function as logic gates. There are patterns that function as memory. There are patterns that replicate themselves. The GoL is Turing complete — you can, in principle, run any computation inside it using nothing but the four rules above.&lt;/p&gt;

&lt;p&gt;This bothered me the first time I really understood it. It still bothers me now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Computational Irreducibility
&lt;/h2&gt;

&lt;p&gt;Wolfram explored what this means in his 2002 book &lt;em&gt;A New Kind of Science&lt;/em&gt;, and one concept from that work has genuinely never left me.&lt;/p&gt;

&lt;p&gt;He called it &lt;strong&gt;computational irreducibility&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When we do physics, we observe a phenomenon, abstract a formula from it, and use that formula to predict future behaviour. A pendulum swings; we write down a differential equation; we evaluate it for any future time &lt;em&gt;t&lt;/em&gt; without having to simulate every intermediate position. The formula &lt;em&gt;collapses&lt;/em&gt; the computation. We get to skip ahead.&lt;/p&gt;

&lt;p&gt;Wolfram argued — and showed, for specific rules — that for certain systems this is simply impossible. There is no closed formula. There is no shortcut. The only way to know what state the system will be in after a million steps is to run it for a million steps. The simulation cannot be compressed. The future is not analytically accessible from the present.&lt;/p&gt;

&lt;p&gt;For the Game of Life specifically: you cannot look at a starting pattern and calculate its state after ten thousand generations without actually computing all ten thousand generations. There is no formula. The universe of the GoL must be &lt;em&gt;lived through&lt;/em&gt;, not solved.&lt;/p&gt;

&lt;p&gt;And that is exactly why the next question feels so unsettling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assuming for a Moment
&lt;/h2&gt;

&lt;p&gt;What if our universe is that kind of system?&lt;/p&gt;

&lt;p&gt;Not a metaphor. The actual conjecture: that physical reality is a cellular automaton, or something functionally equivalent to one — a discrete state space evolving by local rules, step by step, producing complexity that no observer inside it can predict without running the whole thing.&lt;/p&gt;

&lt;p&gt;Wolfram has spent real effort on this. It is not a casual speculation.&lt;/p&gt;

&lt;p&gt;If it is true, then physics as we practise it — observe, abstract, predict — works only in the limited regime where the computation &lt;em&gt;happens&lt;/em&gt; to be compressible. For simple things, on short timescales, the formulas work. The pendulum, the projectile, the ideal gas. We mistake that compressibility for a general property of nature.&lt;/p&gt;

&lt;p&gt;But push far enough into complexity, or far enough into the future, and you hit the irreducibility wall. No equation will get you there. You must simulate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Particle in the Box
&lt;/h2&gt;

&lt;p&gt;Statistical physicists have a word for this wall: entropy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flenygovu78blav1nl5bg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flenygovu78blav1nl5bg.png" alt="Boltzmann — Thermodynamics and Statistical Mechanics" width="682" height="879"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Entropy is a genuinely wild concept — a complete mystery for most people even after years of studying it. I think about it this way. Imagine a sealed box with one particle inside. You have unlimited time and unlimited instruments. You measure the particle's position and momentum to whatever precision your instruments allow. You close the box. Time passes.&lt;/p&gt;

&lt;p&gt;Where is the particle $10^{-27}$ seconds later? Essentially where you left it.&lt;/p&gt;

&lt;p&gt;Where is it 1 second later? Tractable, with some uncertainty from measurement error and from the bouncing geometry.&lt;/p&gt;

&lt;p&gt;Where is it $10^{27}$ seconds later? At this point the uncertainty has compounded so severely that your answer covers essentially the entire box. The measurement you made at the start is no longer useful. It has been drowned by the accumulation of error across every collision.&lt;/p&gt;

&lt;p&gt;This is entropy, in one framing: in an isolated system, the precision with which you can describe the future state can only decrease over time. You started with a measurement. That measurement ages. Every step forward is a step toward irreducibility.&lt;/p&gt;

&lt;p&gt;What I find striking is the shape of this argument. Entropy is usually taught as a thermodynamic concept — heat, disorder, the direction of time. But when I look at it from the side of computational irreducibility, it feels like the same thing stated differently. The system is not yielding its future to analysis. The only way to know where the particle is going to be is to let it go there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maybe entropy is the signature of irreducibility.&lt;/strong&gt; Not just a measure of disorder, but a measure of how far ahead the universe refuses to be calculated.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Edge of Chaos
&lt;/h2&gt;

&lt;p&gt;I do not know whether I would prefer to live in a universe that is, at bottom, a rule table — a matrix of zeros and ones ticking forward under four constraints that nobody chose.&lt;/p&gt;

&lt;p&gt;But if that is what we are, we are clearly in Class 4. Not dead uniformity. Not frozen periodicity. Not meaningless noise.&lt;/p&gt;

&lt;p&gt;We are at the edge of chaos, where gliders emerge from noise, structures persist long enough to collide, and something that looks almost like purpose arises from nothing more than local arithmetic.&lt;/p&gt;

&lt;p&gt;I looked again at the simulation my friend sent me — endless recursive Life inside Life — and I felt strangely comforted.&lt;/p&gt;

&lt;p&gt;I am not sure whether to find that frightening or sufficient.&lt;/p&gt;

</description>
      <category>cellularautomata</category>
      <category>wolfram</category>
      <category>entropy</category>
      <category>philosophy</category>
    </item>
    <item>
      <title>Building a Personal Journal Bot with Telegram, Gemini, and Docker</title>
      <dc:creator>Stephan -All Input Is Error- Bökelmann</dc:creator>
      <pubDate>Sun, 03 May 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maxclerkwell/building-a-personal-journal-bot-with-telegram-gemini-and-docker-5358</link>
      <guid>https://dev.to/maxclerkwell/building-a-personal-journal-bot-with-telegram-gemini-and-docker-5358</guid>
      <description>&lt;p&gt;I have been meaning to journal consistently for years. The friction has never been motivation — it has always been the blank page. Opening a text editor, deciding on a format, remembering what happened, structuring it. By the time I have done all of that, the thought I wanted to capture has either sharpened itself into something obvious or dissolved entirely.&lt;/p&gt;

&lt;p&gt;So I built a bot that does the structuring for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;You send a message to a Telegram bot. The bot asks you one follow-up question. You answer. It might ask another. After two or three exchanges it writes a journal entry, extracts a topic note in Obsidian-compatible markdown, and commits both to a private git repository.&lt;/p&gt;

&lt;p&gt;Voice messages get transcribed. Photos get analysed — Gemini looks at the image and asks what drew your attention there, or what you were trying to capture. The bot remembers what you have been thinking about over the past week and uses that as background context when deciding what to ask next.&lt;/p&gt;

&lt;p&gt;At 23:30 each night it compiles the day's entries into a LaTeX chapter. Every Saturday afternoon it sends a written summary of the week and a compiled PDF of the memoir via Telegram.&lt;/p&gt;

&lt;p&gt;Todos work too. "I need to call the doctor tomorrow" gets classified as a todo for tomorrow's date, not a journal entry. Uncompleted todos roll over to the next day at 22:00.&lt;/p&gt;

&lt;p&gt;The whole thing runs as a Docker container on a cheap VPS. One-command setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  The conversation design
&lt;/h2&gt;

&lt;p&gt;The follow-up question approach took a few iterations to feel right.&lt;/p&gt;

&lt;p&gt;The first version generated all questions upfront — three at once, delivered as a list. It felt like filling in a form. The thought I had was already gone by the time I finished answering question three.&lt;/p&gt;

&lt;p&gt;The second version asked one question at a time, but generated the next question without looking at what had already been answered. So it would ask about context, I would explain, and then it would ask about context again from a different angle. Repetitive.&lt;/p&gt;

&lt;p&gt;The version that works generates each question fresh, with the full history of what has been said so far. The prompt instructs the model to decide whether there is still one genuinely worthwhile thing to ask — or to declare itself done. For technical or project-related thoughts it asks about decisions and next steps. For personal or emotional thoughts it tries to deepen understanding rather than extract facts. If it decides enough has been covered, it returns the string &lt;code&gt;DONE&lt;/code&gt; and the bot moves straight to writing.&lt;/p&gt;

&lt;p&gt;It caps out at three rounds regardless. Three turns of back-and-forth is usually enough to turn a half-formed thought into something writable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The context system
&lt;/h2&gt;

&lt;p&gt;The quality of follow-up questions improves significantly with context. "I'm stuck on the auth refactor again" is a much more useful starting point if the bot knows that you spent the last three days working on that refactor than if it has no background at all.&lt;/p&gt;

&lt;p&gt;After the daily memoir chapter is compiled, the bot saves a compact bullet-point summary of the day — not the full entries, just the key themes, decisions, and open questions. These summaries are loaded as background context when generating follow-up questions.&lt;/p&gt;

&lt;p&gt;The context rolls up over time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every Sunday: a weekly summary is built from that week's daily summaries&lt;/li&gt;
&lt;li&gt;The 1st of every month: a monthly summary is built from the weekly summaries&lt;/li&gt;
&lt;li&gt;January 1st: a yearly summary is built from the monthly summaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is visible to you unless you open the files. It just makes the questions better.&lt;/p&gt;

&lt;h2&gt;
  
  
  On the Gemini API
&lt;/h2&gt;

&lt;p&gt;I had not used the Google Gemini API before this project. A few things I learned:&lt;/p&gt;

&lt;p&gt;The SDK changed. The old &lt;code&gt;google-generativeai&lt;/code&gt; package is deprecated. The new one is &lt;code&gt;google-genai&lt;/code&gt; — note the missing &lt;code&gt;ative&lt;/code&gt; — with a completely different import and client structure: &lt;code&gt;from google import genai&lt;/code&gt;, then &lt;code&gt;genai.Client(api_key=...)&lt;/code&gt;. If you find yourself looking at FutureWarning messages about this, switch packages.&lt;/p&gt;

&lt;p&gt;Model names are a moving target. In the course of a single day I had 404 errors from &lt;code&gt;gemini-2.0-flash&lt;/code&gt;, &lt;code&gt;gemini-2.0-flash-lite&lt;/code&gt;, &lt;code&gt;gemini-1.5-flash&lt;/code&gt;, and &lt;code&gt;gemini-2.5-flash-preview-04-17&lt;/code&gt;. The model that works is &lt;code&gt;gemini-2.5-flash&lt;/code&gt;. Without the preview suffix, without a date suffix.&lt;/p&gt;

&lt;p&gt;For anyone hitting quota limits on the free tier: &lt;code&gt;gemma-3-4b-it&lt;/code&gt; is available through the same API key and has a significantly higher quota. The tradeoff is that it does not support multimodal input — no voice transcription, no image analysis. But for pure text journaling it works well.&lt;/p&gt;

&lt;p&gt;The multimodal API for audio is straightforward once the model name is right. You send the raw audio bytes with a mime type of &lt;code&gt;audio/ogg&lt;/code&gt; and ask for a transcription. Gemini handles Telegram's voice message format without any conversion.&lt;/p&gt;

&lt;h2&gt;
  
  
  The LaTeX memoir
&lt;/h2&gt;

&lt;p&gt;This part was more annoying than expected, in an instructive way.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pdflatex&lt;/code&gt; needs to be run from the directory containing &lt;code&gt;main.tex&lt;/code&gt;, not from a temp directory. The reason is that &lt;code&gt;\input{chapters/2026-05-03}&lt;/code&gt; is a relative path — it resolves correctly when the working directory is &lt;code&gt;memoir/&lt;/code&gt;, and fails with "file not found" when it is anything else. The fix is &lt;code&gt;subprocess.run(..., cwd=str(memoir_dir))&lt;/code&gt; rather than running from a temporary directory.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;microtype&lt;/code&gt; package causes a crash with some font setups unless you disable expansion explicitly: &lt;code&gt;\usepackage[protrusion=true,expansion=false]{microtype}&lt;/code&gt;. This is not obvious from the error message.&lt;/p&gt;

&lt;p&gt;The LaTeX chapter style prompt went through two iterations. The first generated chapters in a reflective, somewhat literary style — long paragraphs, metaphors, the kind of writing that sounds like someone trying to write well. I did not want that. The second prompt specifies: sober, direct, one idea per paragraph, no embellishment, report what happened. The results are considerably more useful for actually remembering what was going on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The SSH key handling
&lt;/h2&gt;

&lt;p&gt;The bot runs in a Docker container and needs to push to a private git repository via SSH. Getting this to work cleanly took longer than the LLM integration.&lt;/p&gt;

&lt;p&gt;The issue is that &lt;code&gt;/root/.ssh&lt;/code&gt; in the container is mounted as read-only (so the host keys cannot be written back), but SSH wants to write &lt;code&gt;known_hosts&lt;/code&gt;. The solution is to copy the keys to a writable temp location in the entrypoint script, add GitHub's known hosts there manually, and point SSH at that location via &lt;code&gt;GIT_SSH_COMMAND&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, SSH will prefer &lt;code&gt;authorized_keys&lt;/code&gt; over actual identity files if it finds them — so the entrypoint explicitly tries &lt;code&gt;id_rsa&lt;/code&gt;, then &lt;code&gt;id_ed25519&lt;/code&gt;, then &lt;code&gt;id_ecdsa&lt;/code&gt; in order, rather than letting SSH pick arbitrarily.&lt;/p&gt;

&lt;p&gt;Git in newer versions also refuses to operate on repositories owned by a different user. Running the container as root and cloning into &lt;code&gt;/repo&lt;/code&gt; means you need &lt;code&gt;git config --global --add safe.directory /repo&lt;/code&gt; before any git operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  The repository structure
&lt;/h2&gt;

&lt;p&gt;After a few weeks of use, the journal repository looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;journal/         — daily markdown files
topics/          — Obsidian-compatible topic notes, one per extracted concept
attachments/     — photos, organised by date
memoir/          — LaTeX source and chapter files
  main.tex
  chapters/
context/         — compact summaries for the bot's memory
  2026-05-03.md
  weeks/
  months/
  years/
todos/           — JSON files, one per day
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The topics directory is the part I find most interesting over time. A topic file for, say, &lt;code&gt;deep-work&lt;/code&gt; gets a new dated section every time you mention something related to it. After a few months you have a document that shows how your thinking on a subject evolved — which decisions you made, which ones you revisited, what changed. Obsidian can render these with the full backlink graph.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is missing
&lt;/h2&gt;

&lt;p&gt;A few things I did not build today that would make this more complete:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Editing&lt;/strong&gt;. There is no way to correct an entry after it has been written. You would have to open the git repository and edit the file directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Search&lt;/strong&gt;. The bot can write and commit, but cannot answer "what did I write about X last month?" — that would require either an embedding index or a smarter read path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multiple users&lt;/strong&gt;. The bot is single-user by design — it checks the chat ID against an environment variable and ignores everything else. Making it multi-user would require persistent state per user, which the current in-memory state dict does not support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running it
&lt;/h2&gt;

&lt;p&gt;The repository is at &lt;a href="https://github.com/MaxClerkwell/telegram_journal_bot" rel="noopener noreferrer"&gt;github.com/MaxClerkwell/telegram_journal_bot&lt;/a&gt;. The README has the full setup walkthrough — BotFather, Google AI Studio API key, deploy keys, the works. The short version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:MaxClerkwell/telegram_journal_bot.git
&lt;span class="nb"&gt;cd &lt;/span&gt;telegram_journal_bot
bash setup.sh
vim .env
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you build something on top of this or find something broken, the issues tab is open.&lt;/p&gt;

</description>
      <category>telegram</category>
      <category>gemini</category>
      <category>docker</category>
      <category>journaling</category>
    </item>
    <item>
      <title>The Recursion Problem in Relational Algebra</title>
      <dc:creator>Stephan -All Input Is Error- Bökelmann</dc:creator>
      <pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maxclerkwell/the-recursion-problem-in-relational-algebra-24l2</link>
      <guid>https://dev.to/maxclerkwell/the-recursion-problem-in-relational-algebra-24l2</guid>
      <description>&lt;p&gt;Relational algebra is the theoretical backbone of every query you will ever write against a relational database. Selection, projection, join, union — five or six operations, and you can express almost any query imaginable. Almost.&lt;/p&gt;

&lt;p&gt;There is one class of problem it cannot touch, and understanding why is one of the more instructive moments in database theory.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Relational Algebra Is Good At
&lt;/h2&gt;

&lt;p&gt;A relational algebra expression takes one or more relations (tables) as input and produces a new relation as output. The expression is finite: a fixed number of operations, applied once, returning a result. This is a feature, not a bug — it makes queries predictable, optimizable, and mathematically well-behaved.&lt;/p&gt;

&lt;p&gt;Consider a simple employee table with columns &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, and &lt;code&gt;manager_id&lt;/code&gt;. Finding all employees who report to a specific manager is straightforward:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;σ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;mana&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;g&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;e&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;r&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mrel mtight"&gt;=&lt;/span&gt;&lt;span class="mord mtight"&gt;42&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;E&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;pl&lt;/span&gt;&lt;span class="mord mathnormal"&gt;oyee&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Done. One selection operation, one pass over the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where It Breaks Down
&lt;/h2&gt;

&lt;p&gt;Now consider a different question: &lt;em&gt;Find all employees who report to manager 42, directly or indirectly — the entire subtree of the org chart.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is a transitive closure problem. To answer it, you need to follow &lt;code&gt;manager_id&lt;/code&gt; links until they run out. But relational algebra has no concept of "repeat this until nothing new is found." Every expression has a fixed depth, determined at query-write time, not at query-run time.&lt;/p&gt;

&lt;p&gt;You could manually unroll it:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;σ&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathrm mtight"&gt;manage&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathrm mtight"&gt;r&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathrm mtight"&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mrel mtight"&gt;=&lt;/span&gt;&lt;span class="mord mtight"&gt;42&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;E&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;pl&lt;/span&gt;&lt;span class="mord mathnormal"&gt;oyee&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;br&gt;

&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;&lt;span class="mrel"&gt;⋈&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;span class="mrel mtight"&gt;=&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;mana&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;g&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;e&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;r&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;E&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;pl&lt;/span&gt;&lt;span class="mord mathnormal"&gt;oyee&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;br&gt;

&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;&lt;span class="mrel"&gt;⋈&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;span class="mrel mtight"&gt;=&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;mana&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;g&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;e&lt;/span&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;r&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size3 size1 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;E&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;pl&lt;/span&gt;&lt;span class="mord mathnormal"&gt;oyee&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;br&gt;

&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;⋮&lt;/span&gt;&lt;span class="mord rule"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;But how many levels deep is the hierarchy? You don't know. And if you did, the query changes every time the data changes. This is not a query — it's a program.&lt;/p&gt;

&lt;p&gt;This is not a gap that got overlooked. Relational algebra was designed around closed-form expressions precisely because that constraint is what makes them analyzable and optimizable. Recursion requires a fixed point — "keep going until the result stops changing" — and that is fundamentally outside the algebra's scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Standard Answer: A Necessary Compromise
&lt;/h2&gt;

&lt;p&gt;SQL introduced &lt;code&gt;WITH RECURSIVE&lt;/code&gt; (common table expressions, CTE) specifically to fill this gap. It works. For org charts, bill-of-materials trees, network routing tables, and any other recursive structure, it is the right tool.&lt;/p&gt;

&lt;p&gt;But it is worth being honest about what it is: an extension &lt;em&gt;beyond&lt;/em&gt; relational algebra, grafted onto SQL because real data is sometimes recursive and databases need to handle it. It is not elegant theory — it is pragmatic engineering. Use it when you need it, but recognize that you have left the clean mathematical foundation behind the moment you do.&lt;/p&gt;

&lt;p&gt;Other approaches handle this more naturally. Datalog, for instance, treats recursion as a first-class concept and sits closer to the theoretical ideal. But Datalog is not what runs in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters for You
&lt;/h2&gt;

&lt;p&gt;When you model a domain, the choice of data structure has consequences. A flat relation is fast, clean, and fully expressible in relational algebra. A recursive structure — a tree, a graph — requires either a recursive SQL extension, a denormalized adjacency list, or a different database paradigm entirely (graph databases like Neo4j exist for exactly this reason).&lt;/p&gt;

&lt;p&gt;Knowing this before you design a schema means you can ask the right question early: &lt;em&gt;Is this data inherently recursive?&lt;/em&gt; If yes, plan accordingly. If no, keep it relational and keep your queries clean.&lt;/p&gt;

&lt;p&gt;The recursion problem is not a flaw in relational algebra. It is a precise statement of what the model is and what it is not. Understanding the boundary is half the job.&lt;/p&gt;

</description>
      <category>database</category>
      <category>teaching</category>
      <category>thga</category>
      <category>relationalalgebra</category>
    </item>
    <item>
      <title>A Database Is Not an API</title>
      <dc:creator>Stephan -All Input Is Error- Bökelmann</dc:creator>
      <pubDate>Fri, 24 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maxclerkwell/a-database-is-not-an-api-ljp</link>
      <guid>https://dev.to/maxclerkwell/a-database-is-not-an-api-ljp</guid>
      <description>&lt;p&gt;When we set up databases for clients at &lt;a href="https://nerd-force1.com" rel="noopener noreferrer"&gt;nerd_force1&lt;/a&gt;, one rule holds without exception: the database is never the outermost layer. This post explains why, and what we put in front of it instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Temptation of Direct Access
&lt;/h2&gt;

&lt;p&gt;Every relational database ships with access control. MySQL has users and privileges. PostgreSQL has roles and schemas. You can, technically, hand a client a connection string and call it done.&lt;/p&gt;

&lt;p&gt;The problem is that a database's built-in access model is designed for database administrators, not for application users. It answers questions like "can this user read this table?" — but not "can this user read &lt;em&gt;their own&lt;/em&gt; rows in this table, filtered by their organization, with rate limiting, and with that action logged?" For anything beyond the simplest internal tooling, the native access control is the wrong abstraction.&lt;/p&gt;

&lt;p&gt;Views and stored procedures are the traditional workaround: define the allowed queries inside the database, expose those, hide the rest. This works, but it has costs. Logic leaks into the database layer where it is hard to version, hard to test, and hard to hand off to a client who does not employ a DBA. The database becomes responsible for things it was not designed to own.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Do Instead
&lt;/h2&gt;

&lt;p&gt;We model the database in UML and express the allowed operations as predefined queries in relational algebra — not SQL code, but the logical structure: what data is needed, how it is joined, what filters apply. SQL is an implementation detail of that intent, not the documentation of it.&lt;/p&gt;

&lt;p&gt;In front of the database we run a thin API layer — typically FastAPI. Each allowed operation becomes an endpoint. The URL is the contract; the SQL behind it is an internal concern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client
  │
  ▼
Keycloak (Authentication &amp;amp; Authorization)
  │
  ▼
FastAPI (Predefined endpoints, input validation, logging)
  │
  ▼
Database (PostgreSQL / MySQL — never directly reachable from outside)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keycloak handles authentication and issues tokens. FastAPI validates those tokens, enforces authorization rules, and routes requests to the appropriate query. The database receives only parameterized queries from a trusted service account. No client ever touches a connection string.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Holds Up
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The database stays clean.&lt;/strong&gt; Schema design, normalization, and indexing are not polluted by access-control workarounds. The data model reflects the domain, not the security requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Behavior is testable and versionable.&lt;/strong&gt; An API endpoint is a function. You can write unit tests for it, version it, document it with OpenAPI, and replace the underlying query without touching the contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authorization is explicit.&lt;/strong&gt; What a user can do is defined in one place — the API layer — not scattered across database roles, view definitions, and stored procedure grants.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The client gets a stable interface.&lt;/strong&gt; If the schema changes, the API absorbs the change. The client's code does not break.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Short Version
&lt;/h2&gt;

&lt;p&gt;A database is for storing and querying data with integrity guarantees. An API is for defining what the outside world is allowed to ask, and how. These are two different jobs. Giving them to the same system means both are done worse than if they were separated.&lt;/p&gt;

&lt;p&gt;When clients come to us with a database problem, we almost always end up drawing the same diagram: a database behind a FastAPI service, with Keycloak in front of that. It is not a clever trick. It is just a clean separation of concerns — and it holds up over time.&lt;/p&gt;

&lt;p&gt;If you are designing a system where a database needs to be accessible to more than one service or one team, start there.&lt;/p&gt;

</description>
      <category>database</category>
      <category>architecture</category>
      <category>fastapi</category>
      <category>keycloak</category>
    </item>
    <item>
      <title>DBMS 01: Why a Filesystem Is Not a Database</title>
      <dc:creator>Stephan -All Input Is Error- Bökelmann</dc:creator>
      <pubDate>Thu, 23 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maxclerkwell/dbms-01-why-a-filesystem-is-not-a-database-3600</link>
      <guid>https://dev.to/maxclerkwell/dbms-01-why-a-filesystem-is-not-a-database-3600</guid>
      <description>&lt;p&gt;Yes, I'm aware: nobody in production actually stores sensor data as 120 CSV files in a flat directory. At least I hope not. But that's precisely why this works as a teaching exercise — it's artificial enough to be harmless, and realistic enough to sting.&lt;/p&gt;

&lt;p&gt;The first practicum I built for the DBMS course at THGA Bochum (&lt;a href="https://github.com/MaxClerkwell/DBMS_01" rel="noopener noreferrer"&gt;DBMS_01&lt;/a&gt;) doesn't teach students how SQL works. It teaches them why SQL exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;Students generate synthetic sensor data: temperature readings from four sensors, three times a day, over thirty days. That's 120 CSV files and 360 rows total. Nothing exotic. Exactly the kind of mess that accumulates when a small team decides "we'll figure out the storage later."&lt;/p&gt;

&lt;p&gt;Then they solve three tasks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Filter and sort readings from one specific sensor.&lt;/li&gt;
&lt;li&gt;Find all measurements above a threshold within a date range.&lt;/li&gt;
&lt;li&gt;Compute min, max, and average per sensor across the full dataset.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Twice. Once with shell tools. Once with SQL against a SQLite database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where It Breaks Down
&lt;/h2&gt;

&lt;p&gt;Task 1 is fine. &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;, done. Everyone feels good about themselves.&lt;/p&gt;

&lt;p&gt;Task 2 is where the cracks appear. Date range filtering across files &lt;em&gt;named by date&lt;/em&gt; means matching filenames against a range, looping, and then filtering contents. It works. It's just longer than it has any right to be for such a simple question.&lt;/p&gt;

&lt;p&gt;Task 3 breaks the illusion completely. Aggregating across 120 files while tracking per-sensor state requires either a temporary file, an associative array, or a nested loop. At this point the shell script isn't solving a data problem anymore — it's solving a parsing problem that shouldn't exist.&lt;/p&gt;

&lt;p&gt;The SQL versions stay flat. Three lines for Task 1. Five for Task 2. One &lt;code&gt;GROUP BY&lt;/code&gt; for Task 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Thing That Lands
&lt;/h2&gt;

&lt;p&gt;The shell pipeline tells the computer &lt;em&gt;how&lt;/em&gt; to find the answer. SQL tells the database &lt;em&gt;what&lt;/em&gt; the answer looks like.&lt;/p&gt;

&lt;p&gt;That distinction — imperative vs. declarative — is easy to define on a slide and very hard to actually feel. Students who write the shell version first and then write the SQL version have the comparison running in their heads. No slide needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why SQLite
&lt;/h2&gt;

&lt;p&gt;No server. No installation. No credentials. &lt;code&gt;sqlite3 sensors.db&lt;/code&gt; and you're in.&lt;/p&gt;

&lt;p&gt;Every removed obstacle is a removed excuse for the concept not to land. The goal is for students to spend their cognitive budget on the query language, not on connection strings.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Doesn't Cover
&lt;/h2&gt;

&lt;p&gt;Transactions, normalization, indexing, query planning — all of that comes later. This practicum makes exactly one claim: &lt;em&gt;for structured data you need to query, a database gives you a better language than a filesystem does.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Once you've felt that, rather than been told it, everything else builds on solid ground.&lt;/p&gt;

&lt;p&gt;The repository is open: &lt;a href="https://github.com/MaxClerkwell/DBMS_01" rel="noopener noreferrer"&gt;github.com/MaxClerkwell/DBMS_01&lt;/a&gt;. If you want to work through it yourself, fork it and work in your own copy — that's the intended workflow. If that concept is new to you, start with the first exercise from my Introduction to Programming course (&lt;a href="https://github.com/MaxClerkwell/PP1" rel="noopener noreferrer"&gt;PP1&lt;/a&gt;), which walks through exactly that.&lt;/p&gt;

</description>
      <category>database</category>
      <category>teaching</category>
      <category>thga</category>
      <category>sql</category>
    </item>
    <item>
      <title>If We Can Measure It, You Can Improve It</title>
      <dc:creator>Stephan -All Input Is Error- Bökelmann</dc:creator>
      <pubDate>Mon, 20 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maxclerkwell/if-we-can-measure-it-you-can-improve-it-1ifh</link>
      <guid>https://dev.to/maxclerkwell/if-we-can-measure-it-you-can-improve-it-1ifh</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmaxclerkwell.github.io%2Fposts%2Fai-gruppe-manifesto%2Fassets%2Fintro-bild.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmaxclerkwell.github.io%2Fposts%2Fai-gruppe-manifesto%2Fassets%2Fintro-bild.jpg" alt="Four people in a VW bus on the way to somewhere that matters" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;





&lt;p&gt;Robotics gives machines hands. AI gives machines judgment. Monitoring gives machines senses. Without the senses, the hands are blind and the judgment is deaf.&lt;/p&gt;





&lt;h2 id="the-apple-on-the-tree"&gt;The Apple on the Tree&lt;/h2&gt;

&lt;p&gt;Ten years ago, as a student, I asked myself a simple question: &lt;strong&gt;why does this apple cost money?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The apple growing on the branch costs nothing. The apple in the store costs something. The difference is human labor — hands that picked it, trucks that moved it, systems that tracked it. Every euro in the price tag is a unit of human time that had to be spent.&lt;/p&gt;

&lt;p&gt;If that is true, then the path to making humanity genuinely richer is not to work more. It is to need fewer human hours per unit of civilization.&lt;/p&gt;

&lt;p&gt;This is why we build what we build.&lt;/p&gt;





&lt;h2 id="the-uncomfortable-truth"&gt;The Uncomfortable Truth&lt;/h2&gt;

&lt;p&gt;Most people fear automation because they think in zero-sum terms: machines take jobs, humans starve. This is wrong — historically wrong and philosophically wrong.&lt;/p&gt;

&lt;p&gt;The printing press didn’t kill scribes to enrich publishers. It made knowledge accessible to everyone. The steam engine didn’t enslave workers — it eventually freed them from fourteen-hour days in the field. Every wave of automation that looks like destruction from the inside looks like liberation from the outside.&lt;/p&gt;

&lt;p&gt;We are at the beginning of the greatest liberation in human history. And most people are still arguing about whether to allow it.&lt;/p&gt;

&lt;p&gt;A few things we hold to be true — and stand behind:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Most operators think they are watching their processes. They are watching indicators. Indicators are not data.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Everyone is racing to add AI to their factory. Nobody asks where the data comes from. You cannot solve in the abstract domain if your transform is broken.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The consultant who tells you to rip and replace is selling you their project, not your solution. The world runs on installed base. It always will.&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Critical infrastructure that isn’t monitored isn’t critical — it’s just unexamined risk.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;





&lt;h2 id="what-we-actually-believe"&gt;What We Actually Believe&lt;/h2&gt;

&lt;p&gt;We build monitoring systems. That sounds modest. It isn’t.&lt;/p&gt;

&lt;p&gt;A machine that cannot monitor itself cannot maintain itself. A machine that cannot maintain itself requires human attention. And humans watching machines is precisely the kind of work that should not require humans.&lt;/p&gt;

&lt;p&gt;We believe: &lt;strong&gt;machines should do everything that machines can do&lt;/strong&gt; — so that humans are free to do everything that only humans can do.&lt;/p&gt;

&lt;p&gt;We are convinced that the soul is not a process. Not a pattern. Not an emergent property of sufficient compute. The creative, the musical, the philosophical, the spiritual — these are not outputs of a sufficiently trained model. They are the signature of something that cannot be automated, and we will never pretend otherwise.&lt;/p&gt;

&lt;p&gt;We work only on projects that move humanity toward a state where more people can live creatively, without worrying about food on the table. If a project does not serve that direction, we are not interested.&lt;/p&gt;





&lt;h2 id="the-transform"&gt;The Transform&lt;/h2&gt;

&lt;p&gt;There is a concept in mathematics that I use every day outside of mathematics: &lt;strong&gt;the Laplace transform&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When a differential equation cannot be solved in its original domain, you transform the problem into an abstract space where the solution becomes tractable — then you transform back. Physics describes the world in measurable quantities. Mathematics provides abstract solutions. Engineers translate those solutions back into reality.&lt;/p&gt;

&lt;p&gt;This is how we approach every problem. We do not fight complexity where it is hardest. We transform. We solve. We return.&lt;/p&gt;

&lt;p&gt;When I chose my field, I looked at robotics first. Exciting, well-funded, visible — and crowded with a thousand companies building manipulators. Then LLMs and autonomous reasoning — equally crowded. But when I looked at actual industry, I saw something unexpected: &lt;strong&gt;the transformation step was broken.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Data was being extracted from PLCs through protocols never designed for scale. Or entered by hand into SAP forms. Neither is a real transform — one is a bottleneck, the other is a human acting as a transducer.&lt;/p&gt;

&lt;p&gt;The gap was not in robotics. The gap was not in AI. The gap was in the instrument itself.&lt;/p&gt;

&lt;p&gt;A monitoring system is that instrument — the transform applied to the physical world.&lt;/p&gt;

&lt;p&gt;The physicist stands before a phenomenon: vibration, temperature, current, pressure. They do not solve it in the noisy, continuous, messy original domain. They describe it formally. That formal description is what makes computation possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The sensor is the act of transformation.&lt;/strong&gt; The data stream is the abstract domain. The anomaly detection, the predictive model, the threshold alert — these are the solutions, computed where solutions are easy. And the actuation, the maintenance call, the adjusted process parameter — that is the inverse transform, back into physical reality.&lt;/p&gt;

&lt;p&gt;But the sensor alone is not enough. A raw signal without a time series database, without cleaning, without context is not usable by any analytical system. The physicist does not just measure — they record, annotate, calibrate, and structure. A monitoring system is the automated physicist: it captures the signal, stores it with temporal precision, strips the noise, adds the context, and delivers something that analysis, prediction, and prevention can actually act on. We design and build every system with that full chain in mind — not just data collection, but data that is ready to be reasoned about.&lt;/p&gt;

&lt;p&gt;You cannot solve problems in the abstract domain if your transform is lossy, delayed, or manual. This is not a metaphor for us. It is the operating principle.&lt;/p&gt;





&lt;h2 id="the-instrument"&gt;The Instrument&lt;/h2&gt;

&lt;p&gt;We believe the sensor must be native to the network.&lt;/p&gt;

&lt;p&gt;Not polled through serial middleware. Not manually entered. Not bridged through industrial protocols that predate the internet. USB and TCP/IP — the same connectivity that made the web universal.&lt;/p&gt;

&lt;p&gt;Our preferred device: a PoE unit that plugs into a switch, receives its address via DHCP, announces itself on the local network via &lt;a href="https://github.com/dominicpoeschko/slook/" rel="noopener noreferrer"&gt;slook&lt;/a&gt;, and is ready to be found. No configuration wizard. No integration project. Plug in — and it works.&lt;/p&gt;

&lt;p&gt;Where network infrastructure does not reach, we go wireless: WiFi with battery, LoRa or cellular with energy harvesting. But we are honest about the physics: &lt;strong&gt;the further a device is from its processing environment, the worse the signal.&lt;/strong&gt; Bandwidth falls. Accuracy falls. Latency rises. This is not a complaint about wireless technology — it is a law of physics, and we respect it. We optimize for proximity. We treat distance as cost.&lt;/p&gt;





&lt;h2 id="the-installed-base-is-the-world"&gt;The Installed Base Is the World&lt;/h2&gt;

&lt;p&gt;We focus on retrofit. Not greenfield.&lt;/p&gt;

&lt;p&gt;This is a philosophical choice as much as a commercial one.&lt;/p&gt;

&lt;p&gt;The factories that exist, the machines that run, the processes that produce — these are not going to be torn down and rebuilt as ideal systems. They are what they are. They represent decades of engineering, capital, and institutional knowledge. Greenfield projects are the exception. The world as it stands is the rule.&lt;/p&gt;

&lt;p&gt;We believe it is better to make what exists measurable than to build perfect systems that never touch the machines that actually run civilization. Every retrofit installation is an act of transformation: a previously opaque process becomes legible, computable, improvable.&lt;/p&gt;

&lt;p&gt;That is where we work. And we have been proving it for twelve years — in nuclear cooling circuits, mine shafts, Montana rivers, rail switching systems, defense platforms, and semiconductor fabs.&lt;/p&gt;





&lt;h2 id="who-we-are"&gt;Who We Are&lt;/h2&gt;

&lt;p&gt;Auto-Intern was founded by Odin Holmes — a hardware and firmware designer from the woods of Oregon — and Prof. Dr. Benjamin Menküc, whose advisory fingerprints remain on the architecture. When I, Stephan Bökelmann, joined in 2014, Odin and I changed the business model: from USB interfaces for automotive OBD to &lt;em&gt;if we can measure it, you can improve it&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Today we are around twenty engineers from physics, electrical engineering, computer science, and cybersecurity. The people who shape the work: Odin on hardware and firmware, Tabea Bökelmann on frontends and APIs, René Glitza on federated and fully homomorphic learning, Philipp Lehmann on security and deployment.&lt;/p&gt;

&lt;p&gt;Alongside Auto-Intern GmbH — the measurement device company — we run nerd_force1, which builds the server-side: our own data center, Kubernetes and Ceph clusters, security-first from the ground up. Sensor to server, owned end to end.&lt;/p&gt;

&lt;p&gt;Our customers are in large manufacturing, critical infrastructure, and defense. Wherever an unmonitored process quickly becomes very expensive.&lt;/p&gt;





&lt;h2 id="the-future-we-are-building-toward"&gt;The Future We Are Building Toward&lt;/h2&gt;

&lt;p&gt;There will be automated production on other planets. Not because we are science fiction enthusiasts, but because it is the logical conclusion of everything we are building toward — supply chains that do not depend on human presence in a specific location, systems that maintain themselves, infrastructure that extends the reach of human civilization without extending its cost.&lt;/p&gt;

&lt;p&gt;We are techno-optimists. The process of transformation has already begun. The question is not whether it will happen — it is whether we will shape it with moral clarity and engineering rigor, or let it happen to us.&lt;/p&gt;

&lt;p&gt;If we do this right, the answer to the apple problem is not poverty. It is abundance. It is a world where more people have more time for the things that only humans can do: to think, to create, to question, to connect, to live as though they were made for something greater than maintenance.&lt;/p&gt;

&lt;p&gt;That is the highest form of human striving we know. And it is the only reason we are here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We are not naive about how long this takes. But we are clear about the direction.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>manifesto</category>
      <category>monitoring</category>
      <category>automation</category>
      <category>autointern</category>
    </item>
    <item>
      <title>Travelling to China with a Peli Case Full of Electronics</title>
      <dc:creator>Stephan -All Input Is Error- Bökelmann</dc:creator>
      <pubDate>Thu, 09 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maxclerkwell/travelling-to-china-with-a-peli-case-full-of-electronics-162a</link>
      <guid>https://dev.to/maxclerkwell/travelling-to-china-with-a-peli-case-full-of-electronics-162a</guid>
      <description>&lt;p&gt;When I went to Dongguan for &lt;a href="https://dev.to/maxclerkwell/emc-in-dongguan-25-years-of-work-4-days-in-a-test-chamber-4f8j"&gt;EMC testing in March&lt;/a&gt;, I brought a Peli case full of custom electronics as checked luggage. This post is the logistics companion to that trip — everything I learned about ATA Carnets, airport customs, and travelling with hardware that looks suspicious to anyone who doesn’t build it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3gu4wx79rxz6ln4ll5go.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3gu4wx79rxz6ln4ll5go.jpg" alt="Peli case packed: foam cut to fit, modules secured, cables coiled alongside" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Not Just Ship It?
&lt;/h2&gt;

&lt;p&gt;Shipping electronics to China for testing and back is a customs nightmare. Import duties, VAT, potential seizure, weeks of waiting. The cleaner solution for temporary export of commercial goods is an &lt;strong&gt;ATA Carnet&lt;/strong&gt; — essentially a passport for your equipment. You declare that you are taking specific items out of your home country, into a foreign country, and bringing them back. No duties, no VAT, as long as everything returns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing the ATA Carnet
&lt;/h2&gt;

&lt;p&gt;In Germany, ATA Carnets are issued by the &lt;strong&gt;IHK&lt;/strong&gt; (Chamber of Commerce). My assistant Vanessa handled most of the paperwork, which I would strongly recommend if you have the option — the form requires a complete list of every item you’re carrying, including descriptions, values, and serial numbers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The serial number point is important.&lt;/strong&gt; Every significant component needs one. We went through our modules and labelled anything that didn’t already have a serial number. This paid off at every customs checkpoint: when an officer picks up a device and asks what it is, you point to the serial number, point to the list, and that’s the end of the conversation. Without serial numbers, you’re explaining what an Edge Compute Module is to a customs officer at 6am.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timeline in Germany:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IHK: approximately 4 business days from application to ready document&lt;/li&gt;
&lt;li&gt;Zollamt Bochum: about one hour in-person, no appointment needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go to the Zollamt in person. They check everything on the list against what you’ve actually packed, then stamp and sign the document. After that, you’re cleared for departure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Packing
&lt;/h2&gt;

&lt;p&gt;I used a Peli case with foam cut to fit. The system was packed snugly enough that nothing moved during the flight. I used two TSA-compliant locks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsoxzsbm5f76ycz9ak6vn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsoxzsbm5f76ycz9ak6vn.jpg" alt="TSA-compliant lock — one of two on the case. One didn't make it back." width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of them didn’t survive the journey. On arrival in Frankfurt I found one lock broken — the TSA key had clearly been used at some point. The second lock was fine. If you’re packing anything sensitive, assume the case will be opened in transit and pack accordingly. Nothing was missing or damaged inside.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frankfurt Airport: Terminal 2 and the Customs Process
&lt;/h2&gt;

&lt;p&gt;If you’re flying to China from Frankfurt, note that most China routes depart from &lt;strong&gt;Terminal 2&lt;/strong&gt;. Allow an extra 15 minutes to get there, and plan at least 3 hours before departure if you’re carrying ATA goods.&lt;/p&gt;

&lt;p&gt;The process at check-in is slightly unusual. You check in at the desk to get your baggage tag — but then you ask for the bag back. Yes, they will be confused. Insist politely. You need to carry the tagged bag yourself to the customs office.&lt;/p&gt;

&lt;p&gt;At the customs office, an officer goes through the entire list with you, item by item. Everything comes out of the case. Everything gets counted. Then it goes back in, gets stamped, and you carry the case to the bag drop that the officer directs you to. &lt;strong&gt;Budget 60 minutes for this process&lt;/strong&gt; on your first time, possibly more. My assistant Vanessa’s preparation made it significantly faster — the serial numbers meant I never had to explain what anything was, just confirm it matched the list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arrival in China
&lt;/h2&gt;

&lt;p&gt;At the Chinese customs on arrival, the process mirrors the German departure. Find a customs officer immediately — don’t walk through the green channel. Show the ATA Carnet, let them inspect, they take one of the pages, sign the document, and you’re done. It takes longer than in Germany. If someone is waiting for you, warn them in advance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apps to Install Before You Leave
&lt;/h2&gt;

&lt;p&gt;Install these before departure, not on arrival:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WeChat&lt;/strong&gt; — essential. Nearly everyone reachable for business in China responds faster on WeChat than email. You also need to wait a few days after installation before you can set a username, so install it early. You can add me: &lt;strong&gt;MaxClerkwell&lt;/strong&gt;. Add your credit card too — WeChat Pay is the default payment method almost everywhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DiDi&lt;/strong&gt; — Chinese Uber. Works reliably, some premium drivers speak English. Every driver will have a bottle of water for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trip.com&lt;/strong&gt; — hotels and train tickets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amap&lt;/strong&gt; — local maps. Google Maps works with a VPN but has gaps in business listings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Translate&lt;/strong&gt; — download the English–Chinese language pack offline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For connectivity: buy a &lt;strong&gt;Holafly eSIM&lt;/strong&gt; before departure (~30 USD/week). Install it correctly before you get to the airport. European SIM data roaming costs are not worth it. Watch out for cheaper plans that prohibit hotspot sharing.&lt;/p&gt;

&lt;p&gt;For everything else: set up a &lt;strong&gt;WireGuard VPN&lt;/strong&gt; before you go. A self-hosted instance is better than a commercial VPN service. WhatsApp and Google work in China with this setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Guangzhou Departure
&lt;/h2&gt;

&lt;p&gt;Leaving China on the return trip is the same process in reverse — except it takes longer. Guangzhou Baiyun Airport has an unusual arrangement where customs and the security check are sequenced in a way that requires you to pass through security with your full luggage including tools. I had a screwdriver set in the Peli case, which triggered additional checks since screwdrivers are not permitted through security onto the aircraft.&lt;/p&gt;

&lt;p&gt;The resolution was diplomatic: I explained the situation, showed the ATA Carnet, and the officers were helpful in directing me to the right channel to drop the tools as checked luggage and continue to the gate. Chinese customs officers were, throughout the trip, genuinely curious rather than obstructive — several wanted to understand what the modules actually did. Being able to explain it simply (a measurement system for industrial ovens) was worth more than any amount of paperwork.&lt;/p&gt;

&lt;p&gt;Allow &lt;strong&gt;90 minutes&lt;/strong&gt; for the Guangzhou departure process if you’re carrying ATA goods.&lt;/p&gt;

&lt;h2&gt;
  
  
  On Arrival Back in Germany
&lt;/h2&gt;

&lt;p&gt;Take the red channel, get the documents signed again on return. Then bring the completed ATA Carnet back to the IHK. This is a formal requirement — failing to return it means you may be liable for import duties on the declared value of everything you took.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary Checklist
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Weeks before departure:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install WeChat, set username, add payment card&lt;/li&gt;
&lt;li&gt;Apply for ATA Carnet at IHK (allow 4+ working days)&lt;/li&gt;
&lt;li&gt;Label all items with serial numbers&lt;/li&gt;
&lt;li&gt;Buy Holafly eSIM, install and test before airport&lt;/li&gt;
&lt;li&gt;Set up WireGuard VPN&lt;/li&gt;
&lt;li&gt;Buy TSA-compliant locks (assume they will be used)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;At Frankfurt airport:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Depart from Terminal 2 (most China routes)&lt;/li&gt;
&lt;li&gt;Allow 3 hours before departure&lt;/li&gt;
&lt;li&gt;Check in, get baggage tag, take bag back&lt;/li&gt;
&lt;li&gt;Go to customs office with ATA Carnet — plan 60 min&lt;/li&gt;
&lt;li&gt;Drop bag where customs officer directs you&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;On arrival in China:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go directly to customs, do not use green channel&lt;/li&gt;
&lt;li&gt;Present ATA Carnet without hesitation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Returning from China (Guangzhou):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow 90 minutes for customs + security&lt;/li&gt;
&lt;li&gt;Pack tools in checked luggage or be prepared to check them separately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Back home:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Return completed ATA Carnet to IHK&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Questions about factory visits in China or EMC testing? Hit me up on WeChat or &lt;a href="https://x.com/maxclerkwell" rel="noopener noreferrer"&gt;X&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>china</category>
      <category>travel</category>
      <category>hardware</category>
      <category>emc</category>
    </item>
    <item>
      <title>EMC in Dongguan: 2.5 Years of Work, 4 Days in a Test Chamber</title>
      <dc:creator>Stephan -All Input Is Error- Bökelmann</dc:creator>
      <pubDate>Wed, 01 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maxclerkwell/emc-in-dongguan-25-years-of-work-4-days-in-a-test-chamber-4f8j</link>
      <guid>https://dev.to/maxclerkwell/emc-in-dongguan-25-years-of-work-4-days-in-a-test-chamber-4f8j</guid>
      <description>&lt;p&gt;In March I flew to Dongguan, China for four days of EMC testing. It was the last major milestone before our reflow oven monitoring system goes into production. After two and a half years of development, the question was simple: does this thing radiate, and can it take a hit?&lt;/p&gt;

&lt;p&gt;It passed. But the story is more interesting than that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgjxkyqf9k27duyhxfi7j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgjxkyqf9k27duyhxfi7j.jpg" alt="Stopover in Shenzhen — the trip begins" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project
&lt;/h2&gt;

&lt;p&gt;The system was commissioned by &lt;strong&gt;GlobalPoint GmbH&lt;/strong&gt; , now part of &lt;strong&gt;Kurtz Ersa GmbH &amp;amp; Co. KG&lt;/strong&gt; , one of the leading manufacturers of reflow soldering equipment. The brief: build a monitoring system that attaches to Ersa’s reflow ovens and gives operators real-time insight into what is actually happening inside the machine — not what the oven &lt;em&gt;thinks&lt;/em&gt; is happening, but what the physics says.&lt;/p&gt;

&lt;p&gt;The development was handled by &lt;a href="https://skainet.io" rel="noopener noreferrer"&gt;&lt;strong&gt;skainet.io&lt;/strong&gt;&lt;/a&gt;, the engineering office of Auto-Intern GmbH. I served as system architect. &lt;a href="https://x.com/odinthenerd" rel="noopener noreferrer"&gt;&lt;strong&gt;Odin Holmes&lt;/strong&gt;&lt;/a&gt; owned firmware and PCB layout, and &lt;a href="https://x.com/tabeatheunicorn" rel="noopener noreferrer"&gt;&lt;strong&gt;Tabea Bökelmann&lt;/strong&gt;&lt;/a&gt; designed and built the frontend. Two and a half years. A lot of iteration.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the System Does
&lt;/h2&gt;

&lt;p&gt;The core of the system is a central compute module — a compact Linux box with a quad-core processor and more RAM than you would expect for its size. It has two separate Ethernet interfaces: one dedicated WAN uplink, and one connected to an integrated switch chip that exposes seven downstream ports, all of them Power over Ethernet.&lt;/p&gt;

&lt;p&gt;Every downstream device is powered and communicated with over those PoE ports. At minimum, the system ships with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A temperature measurement module&lt;/strong&gt; — our own design, with custom-made temperature measurement snakes that take in-situ readings at up to 36 points directly inside the solder oven, streaming live to the compute module.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A digital I/O module&lt;/strong&gt; — reads up to 7 IO-Link sensors and drives a stacklight for at-a-glance status indication.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the drawer we have further modules in various stages of readiness: vibration, IR camera, temperature/humidity, residual O₂, and ultrasonic structure-borne sound. They weren’t part of this certification run, but the architecture is ready for them.&lt;/p&gt;

&lt;p&gt;The compute module auto-detects whatever is connected, loads the calibration files, and exposes the data via REST, WebSocket, and MQTT. On the Ersa machine PC, an Electron frontend consumes those APIs to display profile predictions and process quality indices — CPK and several others.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbzvlgh3h5hekrdm1s3k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbzvlgh3h5hekrdm1s3k.jpg" alt="Everything packed into a Peli case for the flight to Dongguan" width="720" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Travelling with professional electronics across borders comes with its own paperwork. I covered the Peli case setup and the ATA Carnet process in a &lt;a href="https://dev.to/posts/ata-carnet-china-travel/"&gt;separate post&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Test Setup
&lt;/h2&gt;

&lt;p&gt;The lab was &lt;strong&gt;NTC — Nore Detection Technology Co., Ltd&lt;/strong&gt; in Dongguan. We tested against three regulatory frameworks: &lt;strong&gt;CE&lt;/strong&gt; (Europe), &lt;strong&gt;FCC&lt;/strong&gt; (USA), and &lt;strong&gt;CCC&lt;/strong&gt; (China). The full test sequence ran over four days:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Burst (EFT)&lt;/li&gt;
&lt;li&gt;Surge&lt;/li&gt;
&lt;li&gt;5-second power interruption&lt;/li&gt;
&lt;li&gt;Radiated emissions&lt;/li&gt;
&lt;li&gt;Radiated immunity&lt;/li&gt;
&lt;li&gt;Conducted emissions&lt;/li&gt;
&lt;li&gt;Conducted immunity&lt;/li&gt;
&lt;li&gt;Magnetic field&lt;/li&gt;
&lt;li&gt;ESD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We were not going in blind. We had done preliminary testing in Germany, and we have accumulated a fair amount of PoE-specific EMC experience over the years. All our housings are aluminium. The cables are M12 Cat5e SF/UTP — shielded foil, unshielded twisted pair — which behaves predictably in a test chamber if the mechanical coupling is done correctly.&lt;/p&gt;

&lt;p&gt;Everything came back green.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmckm6sh0be6l1321r6q1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmckm6sh0be6l1321r6q1.jpg" alt="Full test bench at NTC — compute module, sensor nodes, M12 PoE cables, ThinkPad for monitoring" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The One Finding
&lt;/h2&gt;

&lt;p&gt;During the test we noticed that the M12 connectors on the downstream devices did not have adequate coupling to their aluminium housings. The anodized surface was acting as an insulator between the connector shell and the enclosure — not ideal when you are trying to maintain a continuous shielded path.&lt;/p&gt;

&lt;p&gt;The fix is straightforward: &lt;strong&gt;serrated lock washers&lt;/strong&gt; (Fächerscheiben) under the M12 connector nut. The teeth cut through the anodizing and create a reliable metal-to-metal bond. We did not need to retest, but this goes into the production build as a specification change.&lt;/p&gt;

&lt;p&gt;It is exactly the kind of thing you catch when you are in a proper chamber with someone experienced watching the traces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8s2x0m65ywgm24yqczoj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8s2x0m65ywgm24yqczoj.jpg" alt="Setup in progress — the NTC technician preparing the conducted immunity test" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lab, and Jees
&lt;/h2&gt;

&lt;p&gt;I was expecting a language barrier and I found one — very few people in and around the lab spoke English. But my project manager, &lt;strong&gt;熊伟&lt;/strong&gt; , who goes by Jees, spoke excellent English and was present throughout all four days. Attentive, knowledgeable, flexible in how we sequenced the tests. He also handed me several EMC tips that I had not encountered before, which alone made the trip worthwhile.&lt;/p&gt;

&lt;p&gt;What surprised me most was the scale of the facility. NTC had far more test chambers than I anticipated — you could run multiple concurrent certifications across different standards without ever waiting for a chamber. The whole operation felt more fluid than equivalent labs I have used in Germany.&lt;/p&gt;

&lt;p&gt;I will be back.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6okb5mkcvxuq6dzc0zp7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6okb5mkcvxuq6dzc0zp7.jpg" alt="Inside the anechoic chamber — radiated emissions test in progress" width="800" height="1067"&gt;&lt;/a&gt; &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frf4fjcc08lif5nc2shxi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frf4fjcc08lif5nc2shxi.jpg" alt="Top-down view of the test arrangement" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond the Lab
&lt;/h2&gt;

&lt;p&gt;Dongguan is not just a testing stop. While I was there I also sat down with a cable manufacturer, visited &lt;a href="https://www.faytech.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Faytech&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://www.nextpcb.com" rel="noopener noreferrer"&gt;&lt;strong&gt;NextPCB&lt;/strong&gt;&lt;/a&gt;, and met with a handful of engineers who had been passed along to me through various contacts. Each of those conversations produced at least one useful lead or piece of information.&lt;/p&gt;

&lt;p&gt;My hotel was next to a sports park. Every morning I ran laps with a group of elderly locals who were entirely unbothered by the foreign engineer in their midst and very friendly once I stopped looking lost. I spent several evenings with Chinese acquaintances — KTV, good restaurants, the kind of conversations that only happen when you are somewhere unfamiliar and have to pay attention.&lt;/p&gt;

&lt;p&gt;Getting around on Didi was seamless. Dongguan is a serious manufacturing city and it moves accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Comes Next
&lt;/h2&gt;

&lt;p&gt;The certification results go back to Kurtz Ersa. Production planning can start. After two and a half years of development it is a strange feeling — not relief exactly, more like the moment when a long measurement finally stabilises and you can read off the value.&lt;/p&gt;

&lt;p&gt;The extended sensor suite (vibration, IR, rest-O₂, ultrasonic) will follow in a subsequent version. The architecture is already there. It just needs time.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The team: &lt;a href="https://x.com/odinthenerd" rel="noopener noreferrer"&gt;Odin Holmes&lt;/a&gt; (firmware, PCB layout), &lt;a href="https://x.com/tabeatheunicorn" rel="noopener noreferrer"&gt;Tabea Bökelmann&lt;/a&gt; (frontend). Developed at &lt;a href="https://skainet.io" rel="noopener noreferrer"&gt;skainet.io&lt;/a&gt; for Kurtz Ersa GmbH &amp;amp; Co. KG.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>hardware</category>
      <category>emc</category>
      <category>china</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>Ten Years of Conferences: What They're Actually For</title>
      <dc:creator>Stephan -All Input Is Error- Bökelmann</dc:creator>
      <pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maxclerkwell/ten-years-of-conferences-what-theyre-actually-for-3k2b</link>
      <guid>https://dev.to/maxclerkwell/ten-years-of-conferences-what-theyre-actually-for-3k2b</guid>
      <description>&lt;p&gt;In 2015 I went to my first real conference. I came back a different engineer. That sounds dramatic, but it's accurate, and it took me a while to understand why. This post is an attempt to write that down — both for myself, after ten years, and for the companies, universities, and open-source projects that keep asking us at &lt;a href="https://skunkforce.org" rel="noopener noreferrer"&gt;Open Skunkforce e.V.&lt;/a&gt; how we think about this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meeting C++, 2015
&lt;/h2&gt;

&lt;p&gt;I went to &lt;strong&gt;Meeting C++ 2015&lt;/strong&gt; with my colleague &lt;a href="https://x.com/odinthenerd" rel="noopener noreferrer"&gt;Odin Holmes&lt;/a&gt;. At that point I thought I was a reasonably competent programmer. I was wrong — not in the way that's demoralising, but in the way that only becomes visible when you're suddenly in a room full of people who have been thinking deeply about problems you haven't encountered yet.&lt;/p&gt;

&lt;p&gt;I didn't know what I didn't know. I heard talks on topics I had no idea existed. I had conversations in corridors that reframed things I thought I understood. Some of those conversations turned into projects. Some turned into friendships that are still going today.&lt;/p&gt;

&lt;p&gt;That's the thing about conferences that doesn't translate into any other format: you cannot Google your way to the questions you haven't thought to ask yet. A talk puts an idea in front of you. A conversation in the hallway afterwards tells you what that idea means in your situation. You go home with a list of things to learn that you didn't know you needed to learn.&lt;/p&gt;

&lt;h2&gt;
  
  
  The List
&lt;/h2&gt;

&lt;p&gt;Over the past ten years, roughly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As attendee or speaker:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meeting C++ — 2015, the beginning&lt;/li&gt;
&lt;li&gt;code:dive, Wrocław — many years in a row&lt;/li&gt;
&lt;li&gt;FOSDEM, Brussels — regularly for eight years&lt;/li&gt;
&lt;li&gt;KiCon US, Chicago 2019 — organised by &lt;a href="https://contextualelectronics.com" rel="noopener noreferrer"&gt;Chris Gammel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ISO C++ Committee Meeting, Kona 2019&lt;/li&gt;
&lt;li&gt;ISO C++ Committee Meeting, Prague 2020&lt;/li&gt;
&lt;li&gt;PANDA and GSI collaboration meetings — multiple&lt;/li&gt;
&lt;li&gt;NVIDIA C++ Meetup, Silicon Valley&lt;/li&gt;
&lt;li&gt;KiCon Asia 2025, Shenzhen — as speaker&lt;/li&gt;
&lt;li&gt;Various smaller conferences and user groups in Germany and the Netherlands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;As organiser (with &lt;a href="https://skunkforce.org" rel="noopener noreferrer"&gt;Open Skunkforce e.V.&lt;/a&gt;):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;emBO++&lt;/strong&gt; — embedded C++ conference, Bochum, every year since 2015&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenTapeout&lt;/strong&gt; — open-source chip design, first edition 2021&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Practical Datascience Conference (PDSC)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KiCon Germany&lt;/strong&gt; — four editions from 2020&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KiCon Europe 2024&lt;/strong&gt; — Rotunde Bochum, 150 attendees&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPPP, Paris&lt;/strong&gt; — marketing and video production, on invitation from Fred Tingaud&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is a lot of rooms. A lot of evenings. A lot of hallways.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Moments That Stay
&lt;/h2&gt;

&lt;p&gt;Three moments from the past decade stand out when I try to articulate what conferences are actually for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kona, 2019.&lt;/strong&gt; I was at the ISO C++ Committee meeting — not as a voting member (I don't hold a DIN seat, so I could participate actively in discussions but not vote), but as a working participant. The Pacific coast outside the venue looked like this every morning:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdj72om7b9cvgzdkc9omb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdj72om7b9cvgzdkc9omb.jpg" alt="Early morning on the Kona waterfront — ISO C++ Committee meeting, February 2019" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One evening I found myself at dinner with &lt;strong&gt;Bjarne Stroustrup&lt;/strong&gt; and &lt;strong&gt;Herb Sutter&lt;/strong&gt;. The conversation was direct, curious, practical. The kind of exchange that only happens when everyone at the table has decided to take the time seriously.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffel8bhsluu37cg0holb5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffel8bhsluu37cg0holb5.png" alt="With Bjarne Stroustrup — Kona, 2019" width="338" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrocław, code:dive.&lt;/strong&gt; &lt;a href="https://sean-parent.stlab.cc" rel="noopener noreferrer"&gt;Sean Parent&lt;/a&gt; and &lt;a href="https://twitter.com/BartoszMilewski" rel="noopener noreferrer"&gt;Bartosz Milewski&lt;/a&gt; ended up with Odin, Tabea, and me in a bar until well past any sensible hour. The conversation went everywhere — category theory, compiler internals, what it means to write software that is honest about what it does. I've learned more in evenings like that than in entire conference days.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2For777i7m8fk84hvv7t0g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2For777i7m8fk84hvv7t0g.jpg" alt="Bar social at code:dive, Wrocław — the evenings are the real conference" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Silicon Valley.&lt;/strong&gt; Tabea and I were at an NVIDIA C++ meetup when &lt;strong&gt;Barbara Gellar&lt;/strong&gt; and &lt;strong&gt;Ansel Sermersheim&lt;/strong&gt; — authors of the &lt;a href="https://www.copperspice.com" rel="noopener noreferrer"&gt;CopperSpice&lt;/a&gt; GUI framework — walked up and asked if we were the people who organised emBO++. That conversation turned into an invitation to stay at their home for four days. We spent those days talking about C++, software design, and what it means to build tools that last. We're still in regular contact today.&lt;/p&gt;

&lt;p&gt;None of these moments were scheduled. None of them appear on any programme. They happened because people who care about the same things ended up in the same place, with time to talk.&lt;/p&gt;

&lt;h2&gt;
  
  
  emBO++: Eleven Years
&lt;/h2&gt;

&lt;p&gt;The arc of emBO++ is the clearest illustration I have of how this compounds over time.&lt;/p&gt;

&lt;p&gt;The first edition, 2015: four people in a room. The second: speakers from Russia to San Francisco, 40 attendees. It felt unreasonably large at the time. By 2020 we had &lt;strong&gt;250 people in Bochum&lt;/strong&gt; — the last edition before COVID.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmaxclerkwell.github.io%2Fposts%2Fwhy-conferences-march-2026%2Fassets%2FIMG_20230324_092047.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmaxclerkwell.github.io%2Fposts%2Fwhy-conferences-march-2026%2Fassets%2FIMG_20230324_092047.jpg" alt="emBO++ 2023 — the conference back at full pace after the pandemic years" width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Going online during the pandemic worked, technically. But something was missing. The talks were fine. The questions-and-answers were fine. What you cannot replicate over video is the moment after the talk ends, when someone turns to the person next to them and says &lt;em&gt;"did you notice that detail he mentioned in passing?"&lt;/em&gt; — and that becomes a two-hour conversation over dinner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ur8olsgu8rt2ci84hax.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ur8olsgu8rt2ci84hax.jpg" alt="emBO++ 2025 — conferences have not fully recovered to pre-COVID numbers yet" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conferences have not fully recovered since COVID. That's the honest picture. Attendance is lower than it was. The habit broke. This bothers me most when I think about students and people early in their careers — the ones who would benefit most from being in a room where the level is higher than anything they've encountered before.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi5yregat4rv0rupsc44z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi5yregat4rv0rupsc44z.jpg" alt="emBO++ 2026 — still running, still worth it" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Broader World
&lt;/h2&gt;

&lt;p&gt;Conferences are not only about software. Some of the most formative meetings I've attended were &lt;strong&gt;PANDA and GSI collaboration meetings&lt;/strong&gt; at &lt;a href="https://www.gsi.de" rel="noopener noreferrer"&gt;GSI Helmholtzzentrum für Schwerionenforschung&lt;/a&gt; in Darmstadt — particle physics, large-scale detector hardware, international teams building instruments that take decades to complete.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmaxclerkwell.github.io%2Fposts%2Fwhy-conferences-march-2026%2Fassets%2FIMG_20220601_131444.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmaxclerkwell.github.io%2Fposts%2Fwhy-conferences-march-2026%2Fassets%2FIMG_20220601_131444.jpg" alt="GSI/FAIR campus in Darmstadt — PANDA collaboration meeting" width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0nrf4fgsxfxmt2a35tz0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0nrf4fgsxfxmt2a35tz0.jpg" alt="Inside a PANDA collaboration session — " width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The dynamics are different from a software conference, but the core is the same: the real work happens in the corridors, at the dinner table, in the conversations that drift far from the official agenda.&lt;/p&gt;

&lt;p&gt;At &lt;strong&gt;KiCon Europe 2024&lt;/strong&gt; in Bochum, the same pattern held. 150 people, two days, the Rotunde. Lukas Hartmann's talk on open hardware CPU modules set off conversations that continued well past the venue closing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqkmhp7penkh0b3k6nb6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqkmhp7penkh0b3k6nb6.jpg" alt="KiCon Europe 2024, Rotunde Bochum — Lukas Hartmann on open hardware" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open Skunkforce also runs smaller, focused events throughout the year — user groups, workshops, single-topic evenings — where the same principles apply at a smaller scale.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo229btiqlqf3t0ys6ggg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo229btiqlqf3t0ys6ggg.jpg" alt="A smaller OSF evening event — focused format, green lighting, engaged audience" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Good Conference Actually Is
&lt;/h2&gt;

&lt;p&gt;Here is what we have learned from organising events for a decade:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Talks set the agenda. Conversations are the output.&lt;/strong&gt; A good talk gives the audience something to argue about. The argument happens in the hallway, at dinner, at the bar. If people leave immediately after the last session, the conference has half-succeeded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The pre-event evening is not optional.&lt;/strong&gt; Every conference we run includes a social the evening before the programme starts. People arrive, meet each other without the structure of sessions, and come to day one already knowing who they want to talk to.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmaxclerkwell.github.io%2Fposts%2Fwhy-conferences-march-2026%2Fassets%2FIMG_20220531_220208.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmaxclerkwell.github.io%2Fposts%2Fwhy-conferences-march-2026%2Fassets%2FIMG_20220531_220208.jpg" alt="emBO++ social evening — the conversations here continue all the way through the programme" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dinner outside the venue belongs in the programme.&lt;/strong&gt; Not a sponsored cocktail reception in the conference hall. A table at a restaurant, with speakers and attendees mixed. The conversations that happen there are the ones people mention years later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;100–200 people is the sweet spot.&lt;/strong&gt; Large enough for real diversity — different industries, backgrounds, experience levels. Small enough that you can find the people you want to talk to, and that the speakers are genuinely accessible. Beyond 300, a conference starts to become a trade fair.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Staying in the hotel room after the conference is the biggest mistake you can make.&lt;/strong&gt; I have made it. Everyone has made it. It is always a mistake.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Offer
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://skunkforce.org" rel="noopener noreferrer"&gt;Open Skunkforce e.V.&lt;/a&gt; organises technical conferences in and around Bochum. We handle everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Programme design and speaker acquisition&lt;/li&gt;
&lt;li&gt;Marketing and public communications&lt;/li&gt;
&lt;li&gt;Venue booking and logistics&lt;/li&gt;
&lt;li&gt;Catering, including the pre-event social and the dinner&lt;/li&gt;
&lt;li&gt;Video recording and post-production&lt;/li&gt;
&lt;li&gt;Publishing recordings openly after the event&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have been doing this for ten years. We have the speaker network, the sponsor relationships, the venue contacts, and — most importantly — the experience of what goes wrong and how to fix it before it matters.&lt;/p&gt;

&lt;p&gt;The format we know best is two days, 100–200 attendees. That maps well to a focused technical community: an open-source project that wants to bring its contributors together, a company that wants to build a developer community around its tools, a university group that wants to connect its research with practitioners in industry.&lt;/p&gt;

&lt;p&gt;If you have been thinking about running a conference but don't know where to start — or have tried and found the logistics overwhelming — that is exactly the problem we exist to solve. Get in touch.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Open Skunkforce e.V. is a registered non-profit based in Bochum. Find us at &lt;a href="https://skunkforce.org" rel="noopener noreferrer"&gt;skunkforce.org&lt;/a&gt; or reach out directly via the contact on this site.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>conferences</category>
      <category>community</category>
      <category>embo</category>
      <category>openskunkforce</category>
    </item>
    <item>
      <title>Dual Uplink for 15 People: Starlink, Heimdall, and Linux Routing</title>
      <dc:creator>Stephan -All Input Is Error- Bökelmann</dc:creator>
      <pubDate>Fri, 27 Feb 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maxclerkwell/dual-uplink-for-15-people-starlink-heimdall-and-linux-routing-3898</link>
      <guid>https://dev.to/maxclerkwell/dual-uplink-for-15-people-starlink-heimdall-and-linux-routing-3898</guid>
      <description>&lt;p&gt;At some point, one internet connection isn’t enough. We hit that point when 15 people were working in the office simultaneously and the line was noticeably sluggish — video calls, git pushes, remote access, all sharing a single uplink. &lt;a href="https://x.com/philippthecron" rel="noopener noreferrer"&gt;Philipp&lt;/a&gt; and I tackled it in February.&lt;/p&gt;

&lt;p&gt;Philipp is our server administrator — still working on his bachelor’s degree, but already operating at a level that leaves many professional admins behind. Together we’ve set up mesh backhauls, VPNs, intranets, a Kubernetes cluster, Ceph storage, Keycloak for all our internal services — and quite a bit more. If a service runs in our office, Philipp either built it or knows every corner of it. The network upgrade in February was one more chapter in a long list.&lt;/p&gt;

&lt;h2 id="the-starting-point"&gt;The Starting Point&lt;/h2&gt;

&lt;p&gt;Our existing network was a standard setup: one uplink, backbone switches behind it, everything running over that single path. It works — until it doesn’t. Either because bandwidth runs out, or because the provider has a bad day. We’d had both.&lt;/p&gt;

&lt;p&gt;The fix was obvious: add a second uplink. We went with &lt;strong&gt;Starlink&lt;/strong&gt; — quick to install, independent of our DSL provider, and well-suited to our location.&lt;/p&gt;

&lt;p&gt;The actual goal was resilience: if one link goes down, the office keeps running without anyone having to intervene.&lt;/p&gt;

&lt;h2 id="heimdall"&gt;Heimdall&lt;/h2&gt;

&lt;p&gt;Between the two uplinks and the existing backbone switches we added a small new rack. Inside: a Debian rack PC, hostname &lt;strong&gt;AI-heimdall&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The name is not accidental. &lt;a href="https://x.com/odinthenerd" rel="noopener noreferrer"&gt;Odin Holmes&lt;/a&gt; — a close collaborator I’ve worked with for years — established the tradition of giving some of our projects and machines names from Norse mythology. The first library Odin and I wrote together was called &lt;strong&gt;Kvasir&lt;/strong&gt;. The habit stuck. Heimdall — the watchman of the gods, who observes all nine worlds and misses nothing — was too fitting for the gateway into our network to pass up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmaxclerkwell.github.io%2Fposts%2Fdual-uplink-feb-2026%2Fassets%2FPXL_20260306_175202894.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmaxclerkwell.github.io%2Fposts%2Fdual-uplink-feb-2026%2Fassets%2FPXL_20260306_175202894.jpg" alt="Setup workspace in the basement — AI-heimdall in the mini-rack on the right, terminal output on the monitor" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI-heimdall has the two uplinks coming in as separate interfaces: &lt;code class="language-plaintext highlighter-rouge"&gt;eno1&lt;/code&gt; for DSL (static IP into the modem), &lt;code class="language-plaintext highlighter-rouge"&gt;eno2&lt;/code&gt; for Starlink via DHCP. The internal network runs on &lt;code class="language-plaintext highlighter-rouge"&gt;eno4&lt;/code&gt; with the &lt;code class="language-plaintext highlighter-rouge"&gt;10.42.0.0/16&lt;/code&gt; address space towards the backbone switches.&lt;/p&gt;

&lt;p&gt;The routing configuration uses two default routes in the Linux main routing table, differentiated by metric: DSL runs with a lower metric and is preferred, Starlink sits alongside it with metric 1003. As long as the DSL gateway is reachable, all traffic goes that way. If DSL drops, Starlink takes over automatically — no manual intervention, no visible outage for anyone in the office.&lt;/p&gt;

&lt;p&gt;For the future, two named tables are already registered in &lt;code class="language-plaintext highlighter-rouge"&gt;/etc/iproute2/rt_tables&lt;/code&gt; — &lt;code class="language-plaintext highlighter-rouge"&gt;starlink&lt;/code&gt; (200) and &lt;code class="language-plaintext highlighter-rouge"&gt;dsl&lt;/code&gt; (201) — as preparation for proper policy routing that directs individual connections over a specific uplink. For now, the failover model is exactly what we need.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmaxclerkwell.github.io%2Fposts%2Fdual-uplink-feb-2026%2Fassets%2FPXL_20260306_205143846.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmaxclerkwell.github.io%2Fposts%2Fdual-uplink-feb-2026%2Fassets%2FPXL_20260306_205143846.jpg" alt=" raw `ip a` endraw  on AI-heimdall — eno1 (DSL), eno2 (Starlink), and eno4 (internal network) all active" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="the-dashboard"&gt;The Dashboard&lt;/h2&gt;

&lt;p&gt;To see what is actually going over which link at any given moment, I wrote a small Python dashboard. It reads the interface statistics for both uplinks and displays throughput and utilisation in real time — simple enough to leave running on a screen in the office.&lt;/p&gt;

&lt;p&gt;It also served as a practical sanity check: the dashboard makes it immediately obvious if everything is routing over one link when it shouldn’t be, or if something is wrong.&lt;/p&gt;

&lt;h2 id="what-it-changed"&gt;What It Changed&lt;/h2&gt;

&lt;p&gt;The bottlenecks are gone — and when the DSL line has a hiccup, nobody in the office notices. That’s the real gain: not more bandwidth on paper, but reliability in practice.&lt;/p&gt;

&lt;p&gt;The actual work was the clean integration on AI-heimdall: two interfaces, correct metric configuration, making sure the Starlink DHCP lease doesn’t write a default route into the main table that displaces DSL. Philipp handled the Starlink installation and the physical setup, and knows every layer of the existing network that AI-heimdall now sits in front of; the routing configuration was my part.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you’re building something similar: two default routes with different metrics in &lt;code class="language-plaintext highlighter-rouge"&gt;/etc/network/interfaces&lt;/code&gt; is enough for clean failover. Per-host load balancing requires additional &lt;code class="language-plaintext highlighter-rouge"&gt;ip rule&lt;/code&gt; entries pointing to named routing tables — that’s the next step we’ll take with the &lt;code class="language-plaintext highlighter-rouge"&gt;starlink&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;dsl&lt;/code&gt; tables already in place.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>networking</category>
      <category>linux</category>
      <category>starlink</category>
      <category>failover</category>
    </item>
    <item>
      <title>Ten Years of PowerSense: Blood, Sweat, and Ferrite Cores</title>
      <dc:creator>Stephan -All Input Is Error- Bökelmann</dc:creator>
      <pubDate>Thu, 15 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maxclerkwell/ten-years-of-powersense-blood-sweat-and-ferrite-cores-268i</link>
      <guid>https://dev.to/maxclerkwell/ten-years-of-powersense-blood-sweat-and-ferrite-cores-268i</guid>
      <description>&lt;p&gt;January 2016. A call came in through a mutual contact — &lt;a href="https://eximentor.de/en/home/" rel="noopener noreferrer"&gt;Steffen Scholle&lt;/a&gt;, at the time an Ex-inspector at DEKRA and today a respected Ex-consultant — connecting us with DB Netz AG. They had a problem: they needed a smarter way to monitor the power supply of their railway switching systems. Three-phase, 16A lines, 1.5mm² cross-section. And they needed it non-intrusively, clip-on, retrofit. No rewiring. No outages. No excuses.&lt;/p&gt;

&lt;p&gt;All the pieces already existed internally — E-field sensing, Hall probes, PoE prototypes — and the moment we heard the requirement, we knew exactly what to assemble. January 2016 was the moment it became real. A customer with a real problem, a real network, and real consequences if the measurements were wrong.&lt;/p&gt;

&lt;p&gt;Ten years later, that call is still one of the most consequential things that ever happened to this company.&lt;/p&gt;




&lt;h2&gt;
  
  
  The First Meeting
&lt;/h2&gt;

&lt;p&gt;We met the DB Netz team in Frankfurt. Their initial idea: an RS-485-connected sensor, daisy-chained across the installation. We declined. Not out of arrogance — out of conviction. RS-485 was the wrong answer to the wrong question. You don't build the future of industrial monitoring on a serial bus from 1983.&lt;/p&gt;

&lt;p&gt;After several conversations, we landed on Power over Ethernet. PoE. We had already used it in smaller projects, already understood its potential. But this was the first time we had the chance to apply it at scale, in a critical infrastructure context, with a customer willing to push it through qualification together with us.&lt;/p&gt;

&lt;p&gt;All the components were there. What could possibly go wrong?&lt;/p&gt;




&lt;h2&gt;
  
  
  The Four Problems Nobody Warned Us About
&lt;/h2&gt;

&lt;p&gt;Quite a lot, as it turned out. As the requirements crystallized, four challenges emerged that would define the next five years:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ultra-low power consumption&lt;/strong&gt; — under 2W total, including all measurement and communication&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extreme EMC conditions&lt;/strong&gt; — railway certification standards, high demands on dielectric strength and touch safety&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ultra-fast installation&lt;/strong&gt; — clip-on, no tools beyond what a technician carries, seconds per unit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-contact voltage measurement&lt;/strong&gt; — no galvanic connection to the conductors&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first three were hard. The fourth was the one that kept us up at night.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkh97421zrl0ypr9rhj1q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkh97421zrl0ypr9rhj1q.jpg" alt="Two bare PCBs: the sensor antenna board (top) and the PoE main board with RJ45 connector (bottom) — before any housing existed" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem of Voltage Without Contact
&lt;/h2&gt;

&lt;p&gt;Here is something most engineers don't think about carefully enough: &lt;strong&gt;voltage is always a potential difference between two points.&lt;/strong&gt; There is no such thing as an absolute voltage. You measure it between two references.&lt;/p&gt;

&lt;p&gt;So how do you measure voltage when you have three phase conductors inside an IT network and you are not galvanically connected to any of them?&lt;/p&gt;

&lt;p&gt;The short answer: you don't measure voltage directly. You measure the time-varying electric field each conductor produces, capture its influence on an antenna, and reconstruct the voltage waveform from there.&lt;/p&gt;

&lt;p&gt;We had built E-field sensing circuits before — that prior work saved us. Our approach: three pairs of flat patch antennas, one pair per phase, placed on the top and bottom surfaces of a thick PCB. The board's normal vector aligned radially to the conductors. Through the 2mm PCB thickness, the electric field decreases with distance as 1/r (long straight conductor approximation), so the two antenna surfaces see slightly different field strengths — and the differential between them scales as 1/r².&lt;/p&gt;

&lt;p&gt;That differential — tiny, noisy, deeply buried in interference — is what we amplified with a carefully tuned op-amp circuit and fed into an ADC. Get the gain and filtering right, and you see clean 50Hz sinusoidal waveforms from three conductors that you have never electrically touched.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fghpiudystxa88vi78amh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fghpiudystxa88vi78amh.jpg" alt="Measured current waveforms for L1, L2, L3 against reference — phase angles 257°, 262°, 323°. Orange (measured) and blue (reference) traces align closely across all three phases." width="800" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To recover absolute voltage values, we added a single galvanically connected voltage reference measurement per switching station — one point in the network where we knew the actual supply voltage. That scalar reference, combined with our normalized E-field measurements, gave us calibrated voltage readings across the entire installation.&lt;/p&gt;

&lt;p&gt;The current measurements, by comparison, were trivial. Hall sensors, standard technique. Or so we thought — until the housing changed everything.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Housing Problem
&lt;/h2&gt;

&lt;p&gt;On the bare PCB, everything worked. Beautiful signals, clean data, happy engineers.&lt;/p&gt;

&lt;p&gt;Then we put it in a housing.&lt;/p&gt;

&lt;p&gt;Together with &lt;a href="https://www.linkedin.com/in/christian-czayka-7769751ab/" rel="noopener noreferrer"&gt;Christian Czayka&lt;/a&gt;, we developed three different enclosure concepts in 3D CAD, printed the first variants, and assembled prototypes: elegant, compact, tool-free installation. The kind of device you look at and immediately understand how to fit it.&lt;/p&gt;

&lt;p&gt;But when the PCB moved inside the housing and the conductors moved further from the antennas, the E-field signals weakened. For voltage sensing, we compensated with higher gain and a tighter frequency filter — manageable.&lt;/p&gt;

&lt;p&gt;For current, the situation was different. We needed to see harmonics — the full spectral content of the current waveform, not just the fundamental. Brute-force amplification destroys that. Filtering kills it. We needed a different approach.&lt;/p&gt;

&lt;p&gt;The solution: &lt;strong&gt;B-field collecting ferrite cores embedded directly into the clamping clips&lt;/strong&gt; that hold the conductors. The geometry was non-trivial. Getting the ferrite dimensions, permeability, and positioning right required weeks of field calculations and FEM simulations — work that fell to &lt;a href="https://www.linkedin.com/in/tabea-b%C3%B6kelmann-0b9794198/" rel="noopener noreferrer"&gt;Tabea Bökelmann&lt;/a&gt;, who I had met during our physics studies and who is, without qualification, significantly better at mathematics than I am.&lt;/p&gt;

&lt;p&gt;The ferrites were custom-manufactured for us, embedded into the prototype clips, and the signals came back. Clean harmonics. Full spectral resolution. A device that worked not just in the lab, but as an actual product that could be assembled by a technician in the field.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fofdfeobofczsfo6ks6v7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fofdfeobofczsfo6ks6v7.jpg" alt="B-field crosstalk between phases: L1→L1 at 100%, L1→L2 at 2.22%, L1→L3 at 0.34% — demonstrating excellent channel isolation from the embedded ferrite geometry." width="799" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqhpckwjuv2wp111jvdi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqhpckwjuv2wp111jvdi.jpg" alt="Three generations of housing (left to right: early black prototype, tall white variant, final grey enclosure with red locking clip and RJ45 port) alongside the ferrite-embedded clamping mechanism for the three-phase conductors." width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Young, Naive, and Almost There
&lt;/h2&gt;

&lt;p&gt;At this point — roughly two years in — we genuinely believed we were almost done. The physics worked. The electronics worked. The housing looked right. We had a team that knew what it was doing.&lt;/p&gt;

&lt;p&gt;We were in our early-to-mid twenties, which explains a lot. Odin was already thirty, which in Oregon hippie years is basically a senior engineer — though it did not appear to grant him any additional realism about the timeline either.&lt;/p&gt;

&lt;p&gt;What followed was two more years of EMC certification at CETECOM, transitioning the housing from 3D-printed prototypes to injection-molded production parts together with LB Kunststoff, and the full qualification cycle under railway standards. Dielectric strength. Touch safety. Vibration. Temperature cycling. The kind of testing that finds every corner you cut and every assumption you made.&lt;/p&gt;

&lt;p&gt;We finished. It took longer than we planned. It always does.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Project Taught Us
&lt;/h2&gt;

&lt;p&gt;Looking back now, a decade later, the skAInet-PowerSense was not just a product. It was an education.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5lm2k2x839jfmzm4dtka.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5lm2k2x839jfmzm4dtka.jpg" alt="Custom-developed PoE infrastructure for the switching stations: QUINT POWER 48V supply feeding two DB ECG PoE8 DIN-rail switches — built because the right hardware simply didn't exist yet." width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frsl701cm9wuhqczj9ihw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frsl701cm9wuhqczj9ihw.jpg" alt="DIANA Edge Computer Gateway — DB-branded prototype of the rack-mount edge compute unit developed alongside the PowerSense to aggregate and forward sensor data." width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PoE first.&lt;/strong&gt; Always. If you commit to PoE, you get TCP/IP, power, and a standards-compliant physical layer in a single cable. Everything the network has to offer becomes accessible to your device. We have not seriously considered an alternative since 2016.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Digitize as close as possible to the source.&lt;/strong&gt; The moment you convert a physical signal to bits, you can apply error correction, checksums, timestamps, and all the reliability mechanisms that decades of networking research have produced. Analog signals degrade. Digital packets either arrive or they don't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A working PCB is not a finished product.&lt;/strong&gt; This is perhaps the hardest lesson for hardware engineers to internalize. The electronics are phase one. What follows is a product development process that is at least as demanding. Today, we structure our projects accordingly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PoC (3–6 months):&lt;/strong&gt; Looks nothing like the product. Integrates all the physical measurement principles. Validates that the science works.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prototype (6–9 months):&lt;/strong&gt; Looks like the product. Manufactured by hand. Proves the form factor and installation concept.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prototype of Product (~12 months):&lt;/strong&gt; Manufactured using the same processes as eventual series production. The first object you can genuinely call a device.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We estimate wrong every time. We estimate less wrong than we used to.&lt;/p&gt;




&lt;p&gt;The skAInet-PowerSense is still in service across DB Netz switching stations. It monitors power supply quality in infrastructure that moves millions of people every day, without anyone on the platform knowing it exists.&lt;/p&gt;

&lt;p&gt;That is what good monitoring looks like.&lt;/p&gt;




&lt;h2&gt;
  
  
  There Is More
&lt;/h2&gt;

&lt;p&gt;This post barely scratches the surface. What I have not covered: inter-channel crosstalk and how we characterized and compensated it, PoE shutdowns caused by drawing too little current (yes, that is a real problem — the standard assumes you need power, not that you are carefully conserving it), the sensitivity of every measurement to the exact relative positioning of conductors and PCB, and the full calibration workflow that ties all of it together into a number you can trust.&lt;/p&gt;

&lt;p&gt;Every one of those deserves its own post. Maybe one day.&lt;/p&gt;




&lt;h2&gt;
  
  
  The People Behind the People
&lt;/h2&gt;

&lt;p&gt;None of this would have been possible without the continuous support of people who believed in the work before it was finished.&lt;/p&gt;

&lt;p&gt;Lukas Jakubczyk and Prof. Gereon Kortenbruck at the PROLAB — Laboratory for Product and Production at THGA Bochum — were there throughout. Prof. Benjamin Menküc, co-founder of Auto-Intern and by this point already a professor for EMC and medical engineering at FH Dortmund, kept advising from the sidelines even after stepping back from day-to-day operations. And Dr. Florian Feldbauer of the EP1 chair at the Faculty of Physics, Ruhr-Universität Bochum, provided the kind of rigorous physics perspective that keeps engineers honest.&lt;/p&gt;

&lt;p&gt;We are genuinely grateful to have RUB, THGA, and FH Dortmund as partners — reliable, deeply professional, and always willing to push back when we need it.&lt;/p&gt;

&lt;p&gt;Our real secret superpower is not the hardware. It is that we take these relationships seriously and keep the conversation going. Regularly, honestly, and without agenda. That is rarer than it sounds.&lt;/p&gt;




&lt;p&gt;If any of this is relevant to something you are building — or if you just want to go deep on non-contact sensing, EMC in rail environments, or PoE power budgeting — come find me on Discord. I enjoy talking about this stuff more than I probably should.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://discord.gg/2BXuUY6hrX" rel="noopener noreferrer"&gt;&lt;span&gt;Discord — Full Stack Engineering&lt;/span&gt;&lt;span&gt;Direct access to me and my colleagues. Webinars, live Q&amp;amp;A, and community discussions for engineers across the full stack.&lt;/span&gt;&lt;span&gt;Join the server →&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>autointern</category>
      <category>hardware</category>
      <category>monitoring</category>
      <category>rail</category>
    </item>
  </channel>
</rss>
