Lesson 03 of 14 · Modules
Engineering with AI vs vibe coding
Two ways to build with AI: 'vibe coding' (accept whatever works, don't read the code) and engineering with AI (spec, tests and review first). When each is appropriate, a spec-driven workflow for infrastructure changes, and how to keep ownership of code you didn't type.
Two modes
| Vibe coding | Engineering with AI | |
|---|---|---|
| Approach | Prompt, run, accept if it works | Spec → plan → tests → small diffs → review |
| Reading the code | Rarely | Always |
| Speed to first result | Very fast | Fast |
| Quality over time | Degrades; hidden bugs and debt | Maintained |
| Fits | Prototypes, experiments, throwaway scripts | Anything that reaches production or others depend on |
Vibe coding is building a sandcastle: quick, fun, and it doesn't matter when the tide takes it. Engineering with AI is building a real house with a very fast helper: you still draw the plans, check the foundations, and inspect every wall, because people will live in it.
When vibe coding is fine
- A prototype to test an idea, in a sandbox, that will be thrown away.
- A personal one-off script on non-critical data.
- Exploring an unfamiliar library before writing a proper spec.
The moment it touches production, shared repos, security, or other people's work, switch modes.
A spec-driven workflow for an infrastructure change
1. Spec (you write it, AI can help refine it):
Goal: Add a PodDisruptionBudget to every Deployment in charts/platform with replicas > 1.
Constraints: minAvailable: 1 unless values override; no change to single-replica workloads;
chart must still pass `helm lint` and our kubeconform CI job.
Acceptance criteria:
- `helm template` output contains a PDB for each multi-replica Deployment, with matching selectors.
- A values flag `pdb.enabled` (default true) removes all PDBs when false.
- Unit tests (helm-unittest) cover both cases.
Out of scope: StatefulSets (separate change).
2. Plan: ask the agent to list files to change and its approach; review the plan before any code.
3. Tests first: have it write the helm-unittest cases; check they fail before the implementation.
4. Implement in small diffs: one concern per commit/PR.
5. Verify: helm lint, helm template | kubeconform, unit tests, policy checks, and your own review of every line. Then normal PR review by a colleague.
Keeping ownership
- Read everything you commit; if you can't explain a line, don't merge it.
- Ask the tool to explain tricky parts, then verify the explanation against docs.
- Keep conventions in project memory (lesson 04) so generated code matches the codebase.
- Watch for silent scope creep: agents sometimes "helpfully" change unrelated files.
Try it: same task, two modes
- Pick a small task (e.g. a script that finds pods without resource limits).
- Vibe-code it: prompt, run, accept. Time it.
- Redo it spec-driven: spec with acceptance criteria, tests first, review. Time it.
- Try to break both versions (namespaces with no pods, pods with init containers, missing permissions).
- Compare: time, defects found, and which one you'd be happy to be paged for.
Going deeper: team practice
- Require specs/acceptance criteria in PRs for AI-heavy changes; reviewers check the diff against them.
- Limit PR size; AI makes large diffs cheap to produce and expensive to review.
- Track defect rates of AI-assisted vs other changes to calibrate trust over time.
Recap
- Vibe coding: fast, low scrutiny; fine for throwaway work only.
- Engineering with AI: spec → plan → tests → small diffs → verify → review.
- Acceptance criteria and tests turn review into verification.
- You own what you merge: read it, understand it, be ready to debug it.
This site is a public version of my personal engineering knowledge hub. It intentionally excludes confidential company information and internal operational details.