The code ran. The tests were green. You shipped it, and for three weeks nothing happened. Then the bill for one service climbs with no matching climb in users. Or a page that loaded instantly takes four seconds, and only for your oldest customers. Or two people open the same screen at the same moment and see different numbers.
Nobody wrote a bug. There is no stack trace, no failing test, no line in the diff that looks wrong. Go back and read the change that caused it and you find something small, tidy and entirely reasonable. That is the shape of the problem this piece is about, and it has one cause: a decision was made in your repository by something that was not you, and nothing about it looked like a decision at the time.
Productize reads the vibe coding vs agentic coding split as a question of ownership rather than of skill. This is Part 2 of a reading of Andrew Ng's AI engineering skills map: Part 1 covered the skills map and the AI-specific skills on it. This one covers the software half, where the silent decisions live.
Part 1The clause the whole essay rests on
Andrew Ng's essay on software fundamentals opens with a question and answers it in one sentence. That sentence does two jobs, and most people read only the first.
Even when you use a coding agent to write all your code, understanding software fundamentals is important for steering your agent to make the tradeoffs you want
or to even know what tradeoffs exist to be made.
The first half is the familiar argument: know enough to point the agent in the right direction. The second half is a stranger claim. The dangerous case is not being wrong about a tradeoff. It is not knowing one was there.
A missing answer is recoverable, because you can see the gap. A missing question is not, because it has already been answered. If you do not know how to configure a cache, you notice, look it up, decide. If you do not know a cache has to be invalidated, nothing prompts you. The agent picked a value, the tests pass, the page is fast, and the wrongness is scheduled for three weeks out.
Andrew Ng names the mechanism plainly: the novice who vibe codes gets working simple applications and, with them, bad tradeoffs, because "the developer didn't know such tradeoffs even existed and therefore did not steer the agent to make the right decisions for their application context". He gives the vocabulary once and never returns to it: "latency, availability, consistency, reliability, maintainability, simplicity, and/or cost". Those seven are what every decision below trades against each other.
Before going further, it is worth seeing the whole map. Ng splits software fundamentals into five pillars, in this order: building full-stack applications · managing data · designing system architectures · making systems secure and reliable · and scaling and operating in production. The rest of this essay walks them in that order. Part 2 stands on the first, Part 3 on the second, where we stay longest, and Part 4 takes the last three together, because they fail by the same mechanism. The other branch of the same map, the six sub-skills of building and deploying AI applications, is Part 4 of the first essay.
Part 2Does agentic coding enable you, or conscript you?
Pillar 1 · Building full-stack applications
It conscripts you. Ng frames the widening of your role as an opportunity, and that framing is too gentle for what happens in a repository.
His version: "Agentic coding enables many developers who previously played more specialized roles (like front-end developer or mobile developer) to play a broader, full-stack role." As a description of capability, true and cheering.
Ng does not say the next part; we do. Enables implies you could decline. You cannot. The cache-invalidation decision and the state-placement decision land in your repository whether or not you know they exist, because the agent has to write something and it will not stop to ask. There is no version of using a coding agent where you decline the decision. There is only a version where you make it without looking. Which changes the advice. Not you may now expand your role, but the expansion already happened, so the only question is whether you are watching.
An agent's lean when nobody is watching is predictable: toward whatever is most written about. The tutorial answer, the single-user answer, the one-process answer. Silence from you is not deferral. It is a decision made by whatever the model has read most of.
Here is what that looks like. You ask for a faster dashboard. The agent adds a five-minute cache in front of the summary query, held in the app's own memory. On your laptop it is correct: one copy of the app, one user. In production there are four copies behind a load balancer, software that spreads incoming requests across whichever copies are running. A user edits a record, the write lands on copy two, and the next request routes back to copy one, where the edit has not happened. So they do it again. Now there are two records. Nothing errored.
The tell is cruel: severity scales with how many copies you run, so it worsens right after you scale up, sending everyone into the scaling change instead of the caching one. The instruction that would have prevented it is not be careful with caching. It is: name the write that invalidates this cache, implement it in the same change, and never keep shared state in one process's memory.
Part 3Why is data the one pillar that fails in silence?
Pillar 2 · Managing data
Because its failure has no output. Every other part of the stack eventually produces something loud: a timeout, an error page, a bill. A data architecture that is missing something produces a confident, plausible answer, and nothing in the system looks different from success.
Ng treats data differently from the other pillars, saying it "deserves special attention" because it is "a foundation that software is built on top of, that is relatively hard to change (even if agents help with migrations)", then makes the essay's one AI-era claim: "Your AI systems will get their own input context from your data source, so if data architecture is chosen poorly, the AI doesn't know what it doesn't know."
This is the same decision the first essay called grounding with data, seen from the other side. That side asks whether to store it as a vector index (searched by closeness of meaning), a knowledge graph (which records what relates to what) or a semantic layer (a mapping that lets a query use business words like customer instead of raw table names) over tables you already have. This side asks how you would ever find out you chose wrong. The mechanism is stronger than the usual complaint that bad data gives bad answers. A model's output is a function of its context, and its context is assembled by code running against your data layer. So the outer edge of what the system can know is the edge of what that layer can return, and nothing inside the model can see that edge from the inside. A person who does not know something can notice the gap. A model handed a truncated context does not experience a truncation. It experiences a complete context.
The sharpest form of this is one sentence long. An empty result set is the same bytes whether the answer is genuinely none, or the question was never answerable from that schema. No query language can express the difference, because the distinction lives in the collection history, meaning how and why those rows came to be gathered at all, and that history is not in the database.
This is the exact opposite of the failure we wrote about in why your AI agent lies to you. There the model invents something that was not in front of it. Here it invents nothing: it answers correctly, over a smaller world, with no signal that the world was smaller. Which is why a better model does not fix it. A better model given the same context reaches the same answer with more polish. It is a data problem that presents as a model problem, so teams misdiagnose it and spend months tuning prompts at it.
Four ways a fact becomes invisible, worth naming on sight:
- Never modelled. The fact was never a field. There is
amountbut noreason. The system answers how much and never why, and no result hints that why was ever answerable. - Deleted by retention. A ninety-day window on interaction history means an agent asked whether this customer has raised this before is structurally unable to say yes about anything older. It will not say it can see ninety days. It will say no. The people who chose that window were balancing storage cost against a compliance rule; nobody in that room was deciding the memory horizon of a system that did not exist yet.
- Not reachable. The row exists and the retrieval path cannot get to it: a filter excluded it, a permission scope hid it, the field was not indexed, a chunk boundary, the point where the document was cut up for retrieval, split the sentence that mattered. The system behaves in every observable way as though the data were not there.
- Not resolved. Two records describe the same customer and nothing links them. The answer is about half a person, and half is not a shape that shows up in an answer. The most dangerous of the four, because the output is not empty. It is partial and plausible.
The everyday version of all four is NULL. In real schemas it stands in for at least five meanings: not applicable, unknown, not yet collected, collected and genuinely empty, and lost in a migration. A model reading a NULL cannot tell them apart. Mostly, neither can we. Which makes one review question unusually productive on a generated schema: what does NULL mean in this column, and is it more than one thing?
Ng states the problem and prescribes nothing, leaving a warning about an invisible failure with no instrument attached. The best instrument we know sits at the boundary where an agent reads. A retrieval tool asked to filter on a dimension the source does not have should return an explicit this field is not available here, never an empty list. That converts a silent absence into a token in the context, which the model can read, report and route around.
Then prove that instrument can fire. Ask something whose answer you know lies outside the retained window, and assert that the system reports it cannot see that far. A retrieval layer that has never once reported a limit has not shown it can detect one.
Part 4The last three pillars fail the same way
Pillars 3-5 · Architecture · Security and reliability · Scaling and operating
Pillar 3, designing system architectures. This is where the essay makes its quietest good point: "the right architecture is a moving target, depending on the phase of the project". The prototype shape is not the first-production shape, and "that too may change as the application scales". Cheap generation is an argument for committing later, not bigger.
Ng stops there. The part we would add is where irreversibility actually sits. One-way doors are not spread evenly through a system. They cluster at its edges. A published URL, an API shape a second client adopted, an ID a user can see, the tenant key that separates one customer's rows from another's once a migration has touched it, where the bytes physically live, what you promised to delete. Internals stay reversible far longer than people assume, and interfaces become irreversible far sooner. The rule that falls out: spend deliberation at the edges, speed in the middle.
Prototypes are the trap inside that rule, because they feel disposable. Their code is. Their published URLs and the real user data they ingested are not: the moment a prototype touches personal data it picks up obligations that outlive every line that created them.
Underneath it is an asymmetry agentic coding created and did not advertise. Generation got dramatically cheaper. Migration got a little cheaper, since an agent rewrites every place in the code that calls the old shape but cannot negotiate a contract change with consumers you do not control. Operating cost did not move at all: it is a function of surface area, meaning how much system exists to be run, watched and secured, and surface area does not care how the code was authored. So cheap generation did not make good architecture cheaper. It made wrong architecture cheaper to acquire and left it exactly as expensive to own. Nobody hand-built seven services for a prototype, because nobody had the weekend. The friction of typing was acting as a limiter on ambition, and removing the friction removed the limiter, not the cost.
Pillar 4, making systems secure and reliable. Ng asks two things here. First a testing strategy: what mix of unit and integration tests, which frameworks, what level of coverage. Second, designing around failure up front, from handling an API that hits a rate limit to graceful degradation, keeping a reduced version running instead of failing outright, to "minimize the blast radius of failures", which is how far a failure spreads before something stops it. He also notes that security work is moving earlier in the lifecycle under "shift left", to the point that "many developers are now also partly security engineers". The failure we keep meeting in this pillar is not too few tests but tests that cannot go red, and checks that report green for the wrong reason. In production, an alert that has never fired and an alert that is broken look identical from outside, because both produce silence.
Pillar 5, scaling and operating in production. Ng's list here is long and unglamorous: configuring the deployment environment, choosing a release strategy, deployment automation, then observability (being able to tell what the system is doing from outside it), alerts, incident management, and finally scaling through sharding (splitting one database across several machines), indexing (pre-building lookups so a query need not scan every row) and replication (keeping copies of the data on more than one machine). The line that ties this pillar back to the whole essay is the instruction to "understand the real load", because real load is the only thing that can tell you whether the in-memory cache across four replicas from Part 2 is a problem yet. The agent gave you code that deploys. It has no way to know what your load looks like, because it has never seen it.
All three of these fail the way the first two did: a decision was made and nobody was looking. The question that works on every pillar is the same one: what would have to be true for this to tell me something?
Part 5What can you ask of a diff tomorrow?
Ask questions you can answer by reading, without running anything. Every one is recognition rather than implementation, which makes the skill acquirable on work you already do. If you cannot answer one from the code in front of you, that is the finding, and the agent's default stands.
- Where does this cached value live: this process, a shared store, the CDN (a cache sitting between your server and the reader), the browser? If this process, how many processes will there be?
- Which write invalidates it, and is that line in this same change?
- Is this authorization check running on the server, or is the server trusting a value the client sent?
- Does this session survive a restart, and a second instance?
- Is this endpoint paginated, returning results in fixed-size pages rather than all at once, and what happens when a customer's list has ten thousand rows?
- For each nullable column: what does
NULLmean here, and is it more than one thing? - What is the retention period here, who decided it, and what does an AI layer lose at that boundary?
- Which consumers outside this repository read these columns, and how were they enumerated? Searching one repo is not an enumeration.
- When a question falls outside what this source holds, does the tool return an empty result or an explicit unsupported?
- What one-line change to the source would make this new test go red?
None of those requires you to write the implementation yourself. That is the point: these fundamentals are learnable at review time, not only in a curriculum.
Ng closes by saying developers who deeply understand how software works "vastly outperform those who vibe code without understanding". He attributes it to an internal study and publishes no figures, so take it as a considered position rather than a measured result. Our version is narrower and harder to argue with: the agent makes the decision either way, and the only variable is whether anyone looked.
The other half of the map is the AI-specific skills sitting on top of these fundamentals: Part 1, Andrew Ng's AI engineering skills map.
Box 3 of the map is using coding agents, and the question the map never asks is who reviews the reviewer. Read it in Part 3, Using Coding Agents.
Box 4 of the map is shaping the build, and the question the map never answers is where the line Andrew Ng tells you to respect actually sits. Read it in Part 4, the line you must measure.
Finished the app but not sure where to host it? We compared the options by job in Hostinger, Vercel, Cloudflare: pick by job, not intro price
- Andrew Ng, AI Engineering Skills Map: Software engineering fundamentals, LinkedIn, 28 Aug 2026. Title, author, date and opening paragraphs verified against the live page on 30 Aug 2026. Later quotations rest on a single copy of the full text.
§