Back to all posts
September 8, 2026Jonas Höttler

Determinism is a feature: why knowing how to code is worth more now, not less

AI can read everything by now: filesystem, database, logs, inbox. That is exactly why fixed paths, clear functions and real software matter more than ever. A case for structure, with an access matrix and code.

AISoftware DevelopmentSecurityOpinion

“Learning to code isn't worth it anymore.” I hear that sentence in every second conversation right now. It is the most comfortable misjudgement of this decade.

The reasoning sounds plausible at first. A model with tool access now reads the filesystem, queries the database, correlates logs, summarises tickets and writes the patch on top. All of that is true, and it is enormous leverage. The conclusion drawn from it is still wrong. Anyone building systems that move money, grant access or retain data needs more fixed paths than ever. Precisely because the model can read everything.

The bottleneck was never typing

What got cheaper is the first draft. What did not get cheaper is operation, guarantee and proof.

The bottleneck in software was never the speed at which someone puts characters into a file. It was the question of which operation you trust, and who answers for it when it goes wrong. AI has not settled that question. It has made it more urgent, because a lot more code is now produced a lot faster.

A model is a distribution, not a contract

A program is a promise: same input, same output, every time. Everything that really counts rests on it. Payroll, interest calculation, access control, dosage calculators, tax logic, tenant isolation.

A language model does not make that promise. Even at temperature: 0, reproducibility is a property of the infrastructure and not of the semantics: different batching, different hardware, a new model snapshot, and the output shifts. That is not a defect, that is the construction.

Fixed functionModel call
Same input, same outputThe output is a sample
Failures are reproducibleFailures are rare and irregular
A change is a diffA change is a new snapshot
Behaviour is fully testableBehaviour is measurable only by sampling
Rollback takes seconds“Rollback” means: hopefully the old model is still served

Both columns are useful. Just not in the same place. The mistake is not using the model. The mistake is using it where a contract is required.

What fixed paths deliver that language cannot

Determinism

The posting produces the same amount twice. Without that property there is no reconciliation, no close and no debugging.

Authorisation

Permissions belong in front of the model, not inside the prompt. “Do not show records from other tenants” is not access control, it is a request. Access control is a WHERE tenant_id = ? the caller cannot override.

Proof

A commit, a migration script, a line in the audit log answer the question “why did this happen?”. “The model decided so” does not answer it, and is worthless to auditors, customers and courts.

Reversibility

Roll back the deploy, reverse the migration, abort the transaction. An operation you cannot take back must not be triggered probabilistically.

Prompt injection is not a bug, it is the shape of the thing

The moment a model reads foreign text, an email, a web page, a PDF, a customer's ticket, the line between data and instruction blurs. This is not an implementation error someone eventually patches away. It follows from both being the same token stream.

The underlying pattern is old and called confused deputy: the attacker holds no permissions, but they can ask someone who does. The answer is architectural, not linguistic. The model does not get a database password. It gets a function.

// not: free write access for the model
// but: a function that can say no

export async function refundOrder(orderId: string, cents: number) {
  if (cents <= 0 || cents > 20_000) throw new Error("amount outside limit");

  const order = await db.order.find(orderId, { tenant: session.tenantId });
  if (!order || order.status !== "paid") throw new Error("not refundable");

  return db.tx(async (t) => {
    await t.refund.create({ orderId, cents, triggeredBy: session.userId });
    await t.audit.log("refund", { orderId, cents, source: "assistant" });
  });
}

The model may call this function. It cannot raise the limit, switch tenants, bypass the status check or suppress the audit entry, because those rules sit outside its reach. That is what guardrails actually means. Not a polite tone in the system prompt, but code that says no.

What the AI may see, and what it may not

“The AI can access all the data” is technically true and operationally the start of the problem. Access is not a yes-or-no question. It is a matrix of data class, path and justification.

Data classPathJustification
Source code, own reposdirectNo personal data, every change is a reviewable diff
Production logsmaskedLogs carry tokens, email addresses, IPs and session IDs, often unnoticed
Customer recordsvia functionPurpose limitation and tenant isolation must be enforced in code, not in the prompt. GDPR Art. 32 requires technical measures
Employee datacodeterminedOnce performance or conduct becomes analysable, works council codetermination applies (in Germany, § 87(1) no. 6 BetrVG)
Keys, tokens, certificatesneverWhatever entered the context is in the log, the cache and the transcript
Write access to productionnever directOnly through reviewed functions with a limit, a transaction and an audit entry
Decisions about peoplenot aloneGDPR Art. 22 protects against purely automated individual decisions. The EU AI Act classifies parts of this as high risk, with obligations phasing in from 2026

These rows are not bureaucracy to be optimised away. They are the reason an application exists at all and not just a chat window.

SaaS is not dead, it is only losing its costume

The claim “AI replaces SaaS” equates software with its surface. The surface is the cheapest part of a product. Expensive and hard is everything else: state across years, migrations without data loss, a role and permission model, tenant isolation, retention periods of eight years and more, availability commitments, data processing agreements, backups you can actually restore.

A chat can produce an invoice. It cannot retain it in an audit-proof way, cannot guarantee that the sum of all postings is correct, and cannot be held liable.

What really changes: the surface gets thinner. The forty-field form becomes a sentence. That does not make the core logic behind it less important, it makes it more exposed. It is now the only place in the system where structure still lives. What is under pressure is per-seat pricing, not the product.

The cost of trying things has fallen. The value of judging them has risen.

Why coding pays more now, not less

  • The prototype costs almost nothing. A Friday-night idea is running by Sunday. If you don't speak the language, you cannot state the idea and cannot check the model's answer.
  • Reading matters more than typing. Code you cannot judge is code you cannot answer for. And somebody always answers for it.
  • Designing interfaces is the actual work. Which functions exist, what they guarantee, where the boundary runs. Whether the model is useful or dangerous hangs on it.
  • Types, tests and contracts are what makes generated code trustworthy at all. The more code comes out of a model, the more value sits in everything that can automatically refute it.

Conclusion

The model is an extraordinary tool. It reads everything, it drafts fast, it carries you over every starting hurdle. But it is a tool for the draft and for the edges, not for the core. The core stays what it was: fixed paths, clear functions, checkable boundaries.

Whoever can build that does not become redundant. They become the person who decides how far the AI is allowed to go.

The legal references in this text are orientation, not legal advice. Retention periods differ by document type and jurisdiction.