Good tools multiply everything downstream. The content pipeline — editors, importers, build systems, validators, preview tools — is a force multiplier: time invested in tooling pays back across every asset and every iteration for the rest of the project. Treat tools as first-class, not as afterthoughts.

---
id: GDC-L1-CONTENT-0001
title: Invest in tools — the pipeline is a force multiplier
layer: L1
domain: CONTENT
subdomain: toolchain
type: contextual
confidence: 4
status: canonical
tags:
  - content
  - tooling
  - pipeline
  - iteration
  - productivity
related:
  - GDC-L1-ARCH-0005
  - GDC-L1-CONTENT-0002
  - GDC-L1-PROTO-0006
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-gregory-game-engine-arch
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> Good tools multiply everything downstream. The content pipeline — editors, importers, build
> systems, validators, preview tools — is a force multiplier: time invested in tooling pays back
> across every asset and every iteration for the rest of the project. Treat tools as
> first-class, not as afterthoughts.

## Rationale
A game is made of thousands of content operations, and each is gated by the tools that perform it,
so a slow, manual, or fragile pipeline taxes every single one — while a good pipeline accelerates
them all [S-gregory-game-engine-arch]. This is leverage: an hour spent making asset import
ten seconds faster saves that ten seconds on every import for years. Tooling is also the enabler
of iteration speed (ARCH-0005, PROTO-0006) and creator empowerment (CONTENT-0002) — you can only
iterate as fast as your tools let you build, preview, and validate. Under-investing in tools is a
false economy that shows up as a slow, painful production; over the life of a project, the
pipeline is one of the highest-ROI investments a team makes.

## Applies when
Any content-heavy project (most games), and any team producing assets repeatedly. The more content
and the longer the project, the higher the return on tooling.

## Does not apply / Exceptions
Very small or short projects may not recoup heavy tool investment — off-the-shelf engine tools
suffice, and building custom tooling would be over-engineering. There's a point of diminishing
returns (gold-plating a tool no one needs). And tools themselves must be maintained; a
half-finished internal tool can cost more than it saves. Invest where content volume justifies it.

## Implementation (kept separate from the principle)
Identify the highest-frequency, highest-pain content operations and improve their tools first.
Measure pipeline times (import, build, preview) the way you'd measure the iteration loop
(ARCH-0005). Prefer improving tools over grinding through manual work. Empower creators with the
tools they need to work without programmers (CONTENT-0002). Keep tools maintained and validated
(CONTENT-0004).

## Disagreement
Tool investment (multiplies output, enables iteration — but costs time and maintenance) vs.
lean/off-the-shelf (start producing sooner — but slower per operation at scale). The return scales
with content volume and project length; tiny projects lean lean, content-heavy ones invest.

## Notes
The tooling principle of CONTENT; the pipeline enabler of iteration speed (ARCH-0005, PROTO-0006)
and creator empowerment (CONTENT-0002). Confidence 4.

gdc-l1-content-0001 invest in tools — the pipeline is a force multiplier content tooling pipeline iteration productivity > good tools multiply everything downstream. the content pipeline — editors, importers, build systems, validators, preview tools — is a force multiplier: time invested in tooling pays back across every asset and every iteration for the rest of the project. treat tools as first-class, not as afterthoughts. a game is made of thousands of content operations, and each is gated by the tools that perform it, so a slow, manual, or fragile pipeline taxes every single one — while a good pipeline accelerates them all [s-gregory-game-engine-arch]. this is leverage: an hour spent making asset import ten seconds faster saves that ten seconds on every import for years. tooling is also the enabler of iteration speed (arch-0005, proto-0006) and creator empowerment (content-0002) — you can only iterate as fast as your tools let you build, preview, and validate. under-investing in tools is a false economy that shows up as a slow, painful production; over the life of a project, the pipeline is one of the highest-roi investments a team makes. any content-heavy project (most games), and any team producing assets repeatedly. the more content and the longer the project, the higher the return on tooling. very small or short projects may not recoup heavy tool investment — off-the-shelf engine tools suffice, and building custom tooling would be over-engineering. there's a point of diminishing returns (gold-plating a tool no one needs). and tools themselves must be maintained; a half-finished internal tool can cost more than it saves. invest where content volume justifies it. identify the highest-frequency, highest-pain content operations and improve their tools first. measure pipeline times (import, build, preview) the way you'd measure the iteration loop (arch-0005). prefer improving tools over grinding through manual work. empower creators with the tools they need to work without programmers (content-0002). keep tools maintained and validated (content-0004). tool investment (multiplies output, enables iteration — but costs time and maintenance) vs. lean/off-the-shelf (start producing sooner — but slower per operation at scale). the return scales with content volume and project length; tiny projects lean lean, content-heavy ones invest. the tooling principle of content; the pipeline enabler of iteration speed (arch-0005, proto-0006) and creator empowerment (content-0002). confidence 4.


Design the pipeline so that designers and artists can create, tune, and iterate content without a programmer in the loop — through data, editors, and in-tool workflows. Every time content work requires a code change, iteration stalls and the people closest to the design lose agency over it.

---
id: GDC-L1-CONTENT-0002
title: Empower creators to build and iterate without programmers
layer: L1
domain: CONTENT
subdomain: empowering-content-creators
type: contextual
confidence: 4
status: canonical
tags:
  - content
  - empowerment
  - data-driven
  - iteration
  - designers
related:
  - GDC-L1-ARCH-0001
  - GDC-L1-CONTENT-0001
  - GDC-L1-ARCH-0005
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-gregory-game-engine-arch
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> Design the pipeline so that designers and artists can create, tune, and iterate content
> *without* a programmer in the loop — through data, editors, and in-tool workflows. Every time
> content work requires a code change, iteration stalls and the people closest to the design lose
> agency over it.

## Rationale
The people who best judge whether a level, ability, or encounter is right are the designers and
artists making it, and they iterate fastest when they can change it directly — which is exactly
what data-driven design enables (ARCH-0001): behavior in editable data, not compiled code
[S-gregory-game-engine-arch]. A pipeline that routes every content tweak through an engineer
creates a bottleneck (the programmer becomes a gate on all iteration), slows the loop that makes
games good (ARCH-0005), and demoralizes creators who can't touch their own work. Empowering
creators — good editors, data assets, live tuning, in-engine authoring — removes the bottleneck
and puts iteration where the judgment is. It's the human payoff of data-driven architecture and
good tooling (CONTENT-0001).

## Applies when
Any project where designers/artists iterate on content — which is nearly all of them. Most
valuable where content volume and iteration are high.

## Does not apply / Exceptions
Some deeply technical content genuinely requires engineering (novel systems, performance-critical
work) — not everything can or should be designer-editable. On tiny teams where the same person
codes and designs, the bottleneck disappears. And empowerment tools have a build cost
(CONTENT-0001's investment) that must be justified by iteration volume.

## Implementation (kept separate from the principle)
Expose content and tuning as data (ARCH-0001) editable in good tools (CONTENT-0001), so creators
work without recompiling. Support live tuning and in-engine authoring (ARCH-0005). Design the
programmer's job as *building the systems and seams*, and the designer's as *filling them with
content* (the "build the seam, fill it later" split). Validate creator-authored data on load so
mistakes fail loudly (CONTENT-0004).

## Disagreement
Creator-empowering pipelines (fast iteration, agency, but tool-building cost) vs. programmer-gated
content (less tooling to build, but a bottleneck at scale). The tradeoff is tool investment vs.
iteration speed — content-heavy, iteration-driven games strongly favor empowerment.

## Notes
The human/agency payoff of data-driven design (ARCH-0001) and tooling (CONTENT-0001); the enabler
of fast iteration (ARCH-0005). Confidence 4.

gdc-l1-content-0002 empower creators to build and iterate without programmers content empowerment data-driven iteration designers > design the pipeline so that designers and artists can create, tune, and iterate content without a programmer in the loop — through data, editors, and in-tool workflows. every time content work requires a code change, iteration stalls and the people closest to the design lose agency over it. the people who best judge whether a level, ability, or encounter is right are the designers and artists making it, and they iterate fastest when they can change it directly — which is exactly what data-driven design enables (arch-0001): behavior in editable data, not compiled code [s-gregory-game-engine-arch]. a pipeline that routes every content tweak through an engineer creates a bottleneck (the programmer becomes a gate on all iteration), slows the loop that makes games good (arch-0005), and demoralizes creators who can't touch their own work. empowering creators — good editors, data assets, live tuning, in-engine authoring — removes the bottleneck and puts iteration where the judgment is. it's the human payoff of data-driven architecture and good tooling (content-0001). any project where designers/artists iterate on content — which is nearly all of them. most valuable where content volume and iteration are high. some deeply technical content genuinely requires engineering (novel systems, performance-critical work) — not everything can or should be designer-editable. on tiny teams where the same person codes and designs, the bottleneck disappears. and empowerment tools have a build cost (content-0001's investment) that must be justified by iteration volume. expose content and tuning as data (arch-0001) editable in good tools (content-0001), so creators work without recompiling. support live tuning and in-engine authoring (arch-0005). design the programmer's job as building the systems and seams, and the designer's as filling them with content (the "build the seam, fill it later" split). validate creator-authored data on load so mistakes fail loudly (content-0004). creator-empowering pipelines (fast iteration, agency, but tool-building cost) vs. programmer-gated content (less tooling to build, but a bottleneck at scale). the tradeoff is tool investment vs. iteration speed — content-heavy, iteration-driven games strongly favor empowerment. the human/agency payoff of data-driven design (arch-0001) and tooling (content-0001); the enabler of fast iteration (arch-0005). confidence 4.


Adopt and enforce consistent naming and folder/organization conventions for assets, code, and data — early. Consistency scales gracefully as the project grows; inconsistency compounds into a mess where nobody can find anything, duplicates proliferate, and tools break. A convention followed is worth more than a perfect one ignored.

---
id: GDC-L1-CONTENT-0003
title: Enforce naming and organization conventions — consistency scales, chaos compounds
layer: L1
domain: CONTENT
subdomain: naming-and-organization
type: contextual
confidence: 4
status: canonical
tags:
  - content
  - naming
  - organization
  - conventions
  - maintainability
related:
  - GDC-L1-CONTENT-0001
  - GDC-L1-TEAM-0004
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-gregory-game-engine-arch
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> Adopt and enforce consistent naming and folder/organization conventions for assets, code, and
> data — early. Consistency scales gracefully as the project grows; inconsistency compounds into
> a mess where nobody can find anything, duplicates proliferate, and tools break. A convention
> followed is worth more than a perfect one ignored.

## Rationale
A game accumulates thousands of files, and the cost of disorganization grows super-linearly: finding assets, avoiding duplicates, wiring up tools, and onboarding people all get harder as the mess deepens [S-gregory-game-engine-arch]. Conventions are cheap to establish and enormously expensive to retrofit, so the time to set them is at the start. They pay off in searchability (you can *find* the thing), tool reliability (automated pipelines depend on predictable names and paths), and shared understanding (a team parallel to "make decisions visible and durable," TEAM-0004 — the convention *is* durable shared knowledge).

## Applies when
Any project past trivial size, and especially any team or long-lived project. The larger the
content and team, the more it matters — but it's cheapest to start on day one.

## Does not apply / Exceptions
A one-person weekend prototype can be loose about it (though even solo devs drift). And
conventions can be over-engineered into bureaucracy that slows people down — the goal is
*consistency that helps*, not a rulebook for its own sake. A simple convention everyone actually
follows beats an elaborate one they route around.

## Implementation (kept separate from the principle)
Keep them simple enough to follow. Enforce them via tooling/validation where possible (CONTENT-0004) rather than vigilance alone. Refactor toward the convention when things drift.

## Disagreement
Little on the value of conventions; the nuance is *how much* structure (lightweight vs. elaborate)
and how strictly to enforce. Over-formalization can bureaucratize; under-structuring invites
chaos. Match the rigor to team and project size.

## Notes
Confidence 4.

gdc-l1-content-0003 enforce naming and organization conventions — consistency scales, chaos compounds content naming organization conventions maintainability > adopt and enforce consistent naming and folder/organization conventions for assets, code, and data — early. consistency scales gracefully as the project grows; inconsistency compounds into a mess where nobody can find anything, duplicates proliferate, and tools break. a convention followed is worth more than a perfect one ignored. a game accumulates thousands of files, and the cost of disorganization grows super-linearly: finding assets, avoiding duplicates, wiring up tools, and onboarding people all get harder as the mess deepens [s-gregory-game-engine-arch]. conventions are cheap to establish and enormously expensive to retrofit, so the time to set them is at the start. they pay off in searchability (you can find the thing), tool reliability (automated pipelines depend on predictable names and paths), and shared understanding (a team parallel to "make decisions visible and durable," team-0004 — the convention is durable shared knowledge). any project past trivial size, and especially any team or long-lived project. the larger the content and team, the more it matters — but it's cheapest to start on day one. a one-person weekend prototype can be loose about it (though even solo devs drift). and conventions can be over-engineered into bureaucracy that slows people down — the goal is consistency that helps, not a rulebook for its own sake. a simple convention everyone actually follows beats an elaborate one they route around. keep them simple enough to follow. enforce them via tooling/validation where possible (content-0004) rather than vigilance alone. refactor toward the convention when things drift. little on the value of conventions; the nuance is how much structure (lightweight vs. elaborate) and how strictly to enforce. over-formalization can bureaucratize; under-structuring invites chaos. match the rigor to team and project size. confidence 4.


Validate content as early as possible — on import, on save, in the build — so bad data fails loudly and immediately, at the point it was created, rather than silently causing a mysterious bug or crash at runtime hours later. Catch it where it's cheap to fix.

---
id: GDC-L1-CONTENT-0004
title: Validate content early — catch bad data on ingest, not at runtime
layer: L1
domain: CONTENT
subdomain: asset-pipeline
type: contextual
confidence: 4
status: canonical
tags:
  - content
  - validation
  - data-integrity
  - pipeline
  - fail-fast
related:
  - GDC-L1-ARCH-0001
  - GDC-L1-CONTENT-0002
  - GDC-L1-QA-0005
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-gregory-game-engine-arch
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> Validate content as early as possible — on import, on save, in the build — so bad data fails
> *loudly and immediately*, at the point it was created, rather than silently causing a mysterious
> bug or crash at runtime hours later. Catch it where it's cheap to fix.

## Rationale
Data-driven design (ARCH-0001) and creator empowerment (CONTENT-0002) mean designers and artists
author lots of data, and some of it will be wrong — a missing reference, an out-of-range value, a
malformed asset. If that error surfaces only at runtime (a crash, a broken level, a subtle
wrong-number bug), it's expensive to trace back to its source and it may ship. Validating on
ingest inverts this: the error is reported to the person who made it, at the moment they made it,
with a clear message — cheap to fix and impossible to miss [S-gregory-game-engine-arch]. This is
the content-pipeline form of "fail fast" and of building quality in rather than testing it out
(QA-0005): the earlier a defect is caught, the cheaper it is, and validation is how you push data
defects to the earliest possible point.

## Applies when
Any data-driven content pipeline — asset imports, data assets, level data, config. The more
designer-authored data, the more validation pays.

## Does not apply / Exceptions
Trivial or one-off data may not justify formal validators. Over-strict validation can also block
legitimate work-in-progress (a designer mid-edit shouldn't be stopped by every transient
inconsistency) — validation should distinguish "broken and shippable" from "unfinished." And
validators are code that must be maintained. Validate what actually breaks; don't gold-plate.

## Implementation (kept separate from the principle)
Add validation at ingest points (import, save) and in the build, reporting errors clearly to the
author. Distinguish hard errors (block) from warnings (flag). Key runtime state by stable
identifiers so missing/renamed content fails cleanly (ARCH-0001/0006, CONTENT-0003). Make the
build fail on invalid content rather than shipping it. Treat this as part of building quality in
(QA-0005).

## Disagreement
Strict early validation (catches defects cheaply, but tooling cost and can block WIP) vs.
permissive pipelines (less friction, but runtime surprises). The balance is validating what
genuinely breaks while not obstructing legitimate in-progress work. Content-heavy, data-driven
projects strongly favor validation.

## Notes
The data-integrity principle of CONTENT; the ingest-time application of fail-fast and "build
quality in" (QA-0005), guarding data-driven content (ARCH-0001, CONTENT-0002). Confidence 4.

gdc-l1-content-0004 validate content early — catch bad data on ingest, not at runtime content validation data-integrity pipeline fail-fast > validate content as early as possible — on import, on save, in the build — so bad data fails loudly and immediately, at the point it was created, rather than silently causing a mysterious bug or crash at runtime hours later. catch it where it's cheap to fix. data-driven design (arch-0001) and creator empowerment (content-0002) mean designers and artists author lots of data, and some of it will be wrong — a missing reference, an out-of-range value, a malformed asset. if that error surfaces only at runtime (a crash, a broken level, a subtle wrong-number bug), it's expensive to trace back to its source and it may ship. validating on ingest inverts this: the error is reported to the person who made it, at the moment they made it, with a clear message — cheap to fix and impossible to miss [s-gregory-game-engine-arch]. this is the content-pipeline form of "fail fast" and of building quality in rather than testing it out (qa-0005): the earlier a defect is caught, the cheaper it is, and validation is how you push data defects to the earliest possible point. any data-driven content pipeline — asset imports, data assets, level data, config. the more designer-authored data, the more validation pays. trivial or one-off data may not justify formal validators. over-strict validation can also block legitimate work-in-progress (a designer mid-edit shouldn't be stopped by every transient inconsistency) — validation should distinguish "broken and shippable" from "unfinished." and validators are code that must be maintained. validate what actually breaks; don't gold-plate. add validation at ingest points (import, save) and in the build, reporting errors clearly to the author. distinguish hard errors (block) from warnings (flag). key runtime state by stable identifiers so missing/renamed content fails cleanly (arch-0001/0006, content-0003). make the build fail on invalid content rather than shipping it. treat this as part of building quality in (qa-0005). strict early validation (catches defects cheaply, but tooling cost and can block wip) vs. permissive pipelines (less friction, but runtime surprises). the balance is validating what genuinely breaks while not obstructing legitimate in-progress work. content-heavy, data-driven projects strongly favor validation. the data-integrity principle of content; the ingest-time application of fail-fast and "build quality in" (qa-0005), guarding data-driven content (arch-0001, content-0002). confidence 4.


Automate repetitive pipeline work (asset processing, builds, validation, deployment) and keep builds reproducible — same inputs, same output, from clean source control. Manual, non-reproducible builds waste time, hide "works on my machine" bugs, and make releases risky.

---
id: GDC-L1-CONTENT-0005
title: Automate the repetitive and keep builds reproducible
layer: L1
domain: CONTENT
subdomain: build-tooling
type: contextual
confidence: 4
status: canonical
tags:
  - content
  - automation
  - build
  - source-control
  - reproducibility
related:
  - GDC-L1-CONTENT-0001
  - GDC-L1-ARCH-0005
  - GDC-L1-QA-0004
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-gregory-game-engine-arch
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> Automate repetitive pipeline work (asset processing, builds, validation, deployment) and keep
> builds **reproducible** — same inputs, same output, from clean source control. Manual,
> non-reproducible builds waste time, hide "works on my machine" bugs, and make releases risky.

## Rationale
Anything done by hand repeatedly is slow, error-prone, and a person's time wasted; automation
converts that recurring cost into a one-time setup that runs reliably forever
[S-gregory-game-engine-arch]. Reproducibility is the deeper requirement: if a build depends on
undocumented local state, one machine's quirks, or manual steps, then bugs can't be reliably
reproduced (QA-0003/0004), releases are gambles, and teammates get different results from the
same source. Automated, reproducible builds from version control give a single source of truth,
catch integration breakage early (continuous builds), and make shipping a routine rather than a
ritual. This is the build/deployment side of investing in tooling (CONTENT-0001) and of the
iteration-speed and quality-in commitments (ARCH-0005, QA-0005).

## Applies when
Any project past prototype scale, and essential for any team (where "works on my machine" bugs and
integration breakage multiply). The larger the team and the more frequent the builds, the more it
matters.

## Does not apply / Exceptions
A solo weekend prototype can build manually. Full CI/CD and elaborate automation have setup and
maintenance cost that tiny projects may not recoup. The principle is "automate what's repetitive
and keep builds reproducible," scaled to the project — not "build a AAA build farm for a game
jam."

## Implementation (kept separate from the principle)
Put everything needed to build in version control; script the build so it's reproducible from a
clean checkout. Automate asset processing, validation (CONTENT-0004), and (as the team grows)
continuous integration. Use non-destructive workflows and source control for assets, not just
code. Make releases a repeatable, tested process (feeding QA-0004 and SHIP). Measure and shorten
build times (part of iteration speed, ARCH-0005).

## Disagreement
Automation/CI investment (reliability, speed, reproducibility — but setup and maintenance cost)
vs. lean manual builds (start sooner, less infrastructure — but brittle and unreproducible at
scale). Scales with team size and build frequency; solo/tiny projects lean manual, teams
automate.

## Notes
The build/reproducibility principle of CONTENT; the deployment side of tooling investment
(CONTENT-0001), enabling reliable bug repro (QA-0003/0004) and shipping (SHIP). Confidence 4.

gdc-l1-content-0005 automate the repetitive and keep builds reproducible content automation build source-control reproducibility > automate repetitive pipeline work (asset processing, builds, validation, deployment) and keep builds reproducible — same inputs, same output, from clean source control. manual, non-reproducible builds waste time, hide "works on my machine" bugs, and make releases risky. anything done by hand repeatedly is slow, error-prone, and a person's time wasted; automation converts that recurring cost into a one-time setup that runs reliably forever [s-gregory-game-engine-arch]. reproducibility is the deeper requirement: if a build depends on undocumented local state, one machine's quirks, or manual steps, then bugs can't be reliably reproduced (qa-0003/0004), releases are gambles, and teammates get different results from the same source. automated, reproducible builds from version control give a single source of truth, catch integration breakage early (continuous builds), and make shipping a routine rather than a ritual. this is the build/deployment side of investing in tooling (content-0001) and of the iteration-speed and quality-in commitments (arch-0005, qa-0005). any project past prototype scale, and essential for any team (where "works on my machine" bugs and integration breakage multiply). the larger the team and the more frequent the builds, the more it matters. a solo weekend prototype can build manually. full ci/cd and elaborate automation have setup and maintenance cost that tiny projects may not recoup. the principle is "automate what's repetitive and keep builds reproducible," scaled to the project — not "build a aaa build farm for a game jam." put everything needed to build in version control; script the build so it's reproducible from a clean checkout. automate asset processing, validation (content-0004), and (as the team grows) continuous integration. use non-destructive workflows and source control for assets, not just code. make releases a repeatable, tested process (feeding qa-0004 and ship). measure and shorten build times (part of iteration speed, arch-0005). automation/ci investment (reliability, speed, reproducibility — but setup and maintenance cost) vs. lean manual builds (start sooner, less infrastructure — but brittle and unreproducible at scale). scales with team size and build frequency; solo/tiny projects lean manual, teams automate. the build/reproducibility principle of content; the deployment side of tooling investment (content-0001), enabling reliable bug repro (qa-0003/0004) and shipping (ship). confidence 4.


Never optimize on intuition. Profile first to find where time actually goes, then optimize only what the profiler proves is slow. Your guess about the bottleneck is usually wrong — measurement is the only reliable guide to where speed lives.

---
id: GDC-L1-PERF-0001
title: Measure, don't guess — profile before you optimize
layer: L1
domain: PERF
subdomain: profiling-first
type: objective
confidence: 5
status: canonical
tags:
  - performance
  - profiling
  - measure-dont-guess
  - optimization
related:
  - GDC-L1-PLAYTEST-0005
  - GDC-L1-PERF-0003
  - GDC-L1-ARCH-0005
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-perf-profiling
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> Never optimize on intuition. **Profile first** to find where time actually goes, then
> optimize only what the profiler proves is slow. Your guess about the bottleneck is
> usually wrong — measurement is the only reliable guide to where speed lives.

## Rationale
Human intuition about performance is notoriously unreliable: the code that *looks*
expensive often isn't, and the real cost hides somewhere unglamorous (a redundant load, a
cache-hostile loop, an accidental per-frame allocation). Optimizing without measuring means
you spend effort on code that wasn't the problem, complicate the codebase, and frequently
don't move the frame rate at all [S-perf-profiling]. A profiler replaces the guess with a
fact — *this* function, *this* system, *this* draw call is eating the frame — so every hour
of optimization is aimed at something that matters. "Measure, don't guess" is the same
discipline as judging design by observed play (DESIGN-0001) and player behavior
(PLAYTEST-0001), applied to performance.

## Applies when
Any performance work, on any platform. The instant the question is "why is this slow?" the
answer is "profile it," not "I bet it's X."

## Does not apply / Exceptions
Obvious, cheap wins with known costs (don't load a 4K texture for a 32px icon) don't need a
profiling session — some things are known-slow by construction. And profiling itself must be
representative: profile on target hardware under real workloads, since a debug build on a
dev machine can mislead. But even "obvious" fixes should be *verified* by measurement, since
the obvious cause is often not the actual one.

## Implementation (kept separate from the principle)
Profile on representative hardware and content, not a beefy dev box on an empty scene.
Identify the single biggest cost, fix it, then *re-profile* (the bottleneck moves — see
PERF-0003). Distinguish CPU-bound from GPU-bound before choosing a fix (PERF-0004). Keep
before/after measurements so you can prove a change helped rather than assuming it did.

## Disagreement
No serious dissent: profile-first is near-universal engineering practice. The only nuance is
how much "obvious" optimization to do without formal profiling — and even there, the safe
answer is to verify.

## Notes
The foundational PERF principle and the resolution of the `PERF-0001` forward-reference from
PLAYTEST-0005 (telemetry/measurement). Shares the "measure, don't guess" ethos that runs
through DESIGN-0001, PLAYTEST-0001/0005, and SYS-0002. Confidence 5.

gdc-l1-perf-0001 measure, don't guess — profile before you optimize performance profiling measure-dont-guess optimization > never optimize on intuition. profile first to find where time actually goes, then optimize only what the profiler proves is slow. your guess about the bottleneck is usually wrong — measurement is the only reliable guide to where speed lives. human intuition about performance is notoriously unreliable: the code that looks expensive often isn't, and the real cost hides somewhere unglamorous (a redundant load, a cache-hostile loop, an accidental per-frame allocation). optimizing without measuring means you spend effort on code that wasn't the problem, complicate the codebase, and frequently don't move the frame rate at all [s-perf-profiling]. a profiler replaces the guess with a fact — this function, this system, this draw call is eating the frame — so every hour of optimization is aimed at something that matters. "measure, don't guess" is the same discipline as judging design by observed play (design-0001) and player behavior (playtest-0001), applied to performance. any performance work, on any platform. the instant the question is "why is this slow?" the answer is "profile it," not "i bet it's x." obvious, cheap wins with known costs (don't load a 4k texture for a 32px icon) don't need a profiling session — some things are known-slow by construction. and profiling itself must be representative: profile on target hardware under real workloads, since a debug build on a dev machine can mislead. but even "obvious" fixes should be verified by measurement, since the obvious cause is often not the actual one. profile on representative hardware and content, not a beefy dev box on an empty scene. identify the single biggest cost, fix it, then re-profile (the bottleneck moves — see perf-0003). distinguish cpu-bound from gpu-bound before choosing a fix (perf-0004). keep before/after measurements so you can prove a change helped rather than assuming it did. no serious dissent: profile-first is near-universal engineering practice. the only nuance is how much "obvious" optimization to do without formal profiling — and even there, the safe answer is to verify. the foundational perf principle and the resolution of the perf-0001 forward-reference from playtest-0005 (telemetry/measurement). shares the "measure, don't guess" ethos that runs through design-0001, playtest-0001/0005, and sys-0002. confidence 5.


Write clear, correct, simple code first; optimize later, and only where measurement demands it. Premature optimization wastes effort on code that will change, obscures the design, and usually targets the wrong thing — "premature optimization is the root of all evil." Correctness and clarity come before speed.

---
id: GDC-L1-PERF-0002
title: Don't optimize prematurely — implement simply first
layer: L1
domain: PERF
subdomain: optimization-timing
type: contextual
confidence: 4
status: canonical
tags:
  - performance
  - premature-optimization
  - simplicity
  - iteration
related:
  - GDC-L1-PERF-0001
  - GDC-L1-DESIGN-0007
  - GDC-L1-ARCH-0006
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-knuth-premature
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> Write clear, correct, simple code first; optimize later, and only where measurement
> demands it. Premature optimization wastes effort on code that will change, obscures the
> design, and usually targets the wrong thing — "premature optimization is the root of all
> evil." Correctness and clarity come before speed.

## Rationale
Early in development the game is in flux — systems get rebuilt, content multiplies, the
performance profile shifts drastically — so optimizations made before the design settles are
often rendered irrelevant or actively harmful by later changes [S-knuth-premature].
Optimizing early also costs twice: once to write the complex fast version, and again to
understand and maintain it, all while the simple version would have been fine (only a small
fraction of code — Knuth's "critical 3%" — ever meaningfully affects runtime). Clear code is
also easier to *correctly* optimize later, once profiling (PERF-0001) shows where it's
actually needed. Simplicity first keeps the code malleable during the iteration that makes
the game good (PROTO/ARCH-0005).

## Applies when
Most feature and gameplay code during active development, before the design and content have
stabilized enough for the performance profile to be meaningful.

## Does not apply / Exceptions
Two important limits. First, *architectural* decisions that are expensive to reverse — core
data layout, threading model, entity architecture — must consider performance up front,
because you can't "profile it later" your way out of a fundamentally wrong foundation
(this is the counter-tension, and it's real). Second, avoid *premature pessimization*:
deliberately writing gratuitously wasteful code "to optimize later" is its own mistake —
don't optimize early, but don't be needlessly slow either. Known hot paths and shipping
platform limits also warrant earlier attention.

## Implementation (kept separate from the principle)
Default to the simplest correct implementation. Reserve optimization for what the profiler
flags (PERF-0001) on the critical path (PERF-0003). *Do* think about performance for
hard-to-change architecture (data layout, PERF-0005; state/serialization, ARCH-0006) early.
Otherwise, keep code clear and change it when measurement says to.

## Disagreement
The genuine tension: "premature optimization is evil" (defer, measure, keep it simple) vs.
"architecture is destiny" (some performance-shaping decisions are effectively permanent and
must be made early). The reconciliation most engineers accept: defer *local* optimizations
(algorithms, micro-tuning) until measured, but make *structural* performance decisions
consciously up front. Judge which kind you're facing.

## Notes
Pairs with PERF-0001 (measure) and PERF-0003 (bottleneck); its "architecture early" exception
connects to ARCH-0006 (serialization/state) and PERF-0005 (data layout). Allies with
elegance/simplicity (DESIGN-0007). Confidence 4.

gdc-l1-perf-0002 don't optimize prematurely — implement simply first performance premature-optimization simplicity iteration > write clear, correct, simple code first; optimize later, and only where measurement demands it. premature optimization wastes effort on code that will change, obscures the design, and usually targets the wrong thing — "premature optimization is the root of all evil." correctness and clarity come before speed. early in development the game is in flux — systems get rebuilt, content multiplies, the performance profile shifts drastically — so optimizations made before the design settles are often rendered irrelevant or actively harmful by later changes [s-knuth-premature]. optimizing early also costs twice: once to write the complex fast version, and again to understand and maintain it, all while the simple version would have been fine (only a small fraction of code — knuth's "critical 3%" — ever meaningfully affects runtime). clear code is also easier to correctly optimize later, once profiling (perf-0001) shows where it's actually needed. simplicity first keeps the code malleable during the iteration that makes the game good (proto/arch-0005). most feature and gameplay code during active development, before the design and content have stabilized enough for the performance profile to be meaningful. two important limits. first, architectural decisions that are expensive to reverse — core data layout, threading model, entity architecture — must consider performance up front, because you can't "profile it later" your way out of a fundamentally wrong foundation (this is the counter-tension, and it's real). second, avoid premature pessimization: deliberately writing gratuitously wasteful code "to optimize later" is its own mistake — don't optimize early, but don't be needlessly slow either. known hot paths and shipping platform limits also warrant earlier attention. default to the simplest correct implementation. reserve optimization for what the profiler flags (perf-0001) on the critical path (perf-0003). do think about performance for hard-to-change architecture (data layout, perf-0005; state/serialization, arch-0006) early. otherwise, keep code clear and change it when measurement says to. the genuine tension: "premature optimization is evil" (defer, measure, keep it simple) vs. "architecture is destiny" (some performance-shaping decisions are effectively permanent and must be made early). the reconciliation most engineers accept: defer local optimizations (algorithms, micro-tuning) until measured, but make structural performance decisions consciously up front. judge which kind you're facing. pairs with perf-0001 (measure) and perf-0003 (bottleneck); its "architecture early" exception connects to arch-0006 (serialization/state) and perf-0005 (data layout). allies with elegance/simplicity (design-0007). confidence 4.


Performance work has sharply diminishing returns off the critical path. Find the single biggest bottleneck, fix it, re-profile, and repeat. Time spent speeding up code that isn't the bottleneck buys nothing — the frame is only as fast as its slowest necessary part.

---
id: GDC-L1-PERF-0003
title: Optimize the bottleneck — the critical few, not the trivial many
layer: L1
domain: PERF
subdomain: optimization-timing
type: objective
confidence: 4
status: canonical
tags:
  - performance
  - bottleneck
  - profiling
  - diminishing-returns
related:
  - GDC-L1-PERF-0001
  - GDC-L1-PERF-0004
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-perf-profiling
  - S-knuth-premature
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> Performance work has sharply diminishing returns off the critical path. Find the single
> biggest bottleneck, fix it, **re-profile**, and repeat. Time spent speeding up code that
> isn't the bottleneck buys nothing — the frame is only as fast as its slowest necessary
> part.

## Rationale
Runtime is dominated by a small fraction of the code — Knuth's "critical 3%" — so a game's
frame time is gated by whichever system takes longest, and shaving a function that isn't
that system changes the frame rate not at all [S-perf-profiling] [S-knuth-premature]. This
makes optimization a targeting problem: the payoff comes from attacking the *current* top
cost, not from broad, even effort across the codebase. And bottlenecks move — fix the top
one and a different system becomes the new ceiling — which is why optimization is a *loop*
(profile → fix the top cost → re-profile) rather than a single pass. Working the loop
concentrates every hour where it actually buys frame time.

## Applies when
Any optimization pass. The rule for *what* to optimize: whatever profiling currently shows
as the largest cost on the critical path.

## Does not apply / Exceptions
Death by a thousand cuts is real: sometimes there is no single fat bottleneck but many small
costs (lots of tiny per-frame allocations, thousands of trivial draw calls), and the fix is
a systemic pattern change rather than one hot function. Frame-time *spikes* (hitches) also
need different treatment than steady-state cost — a rare 40 ms stall hurts more than a
slightly higher average. And memory or load-time budgets are separate axes from frame time.

## Implementation (kept separate from the principle)
Profile (PERF-0001), fix the top cost, and immediately re-profile to find the new top cost —
don't optimize a list of pre-planned targets, follow the profiler. Watch for the
many-small-costs pattern (attack it structurally). Track spikes separately from averages.
Stop when the frame fits the budget (PERF-0004), not when the code is "as fast as possible."

## Disagreement
Little on "optimize the bottleneck"; the practical nuance is single-fat-bottleneck (attack
it directly) vs. many-small-costs (change the pattern) vs. spikes (hunt the stall) — different
shapes of performance problem needing different responses, all still guided by measurement.

## Notes
Follows directly from PERF-0001 (measure) and feeds PERF-0004 (budget defines "fast enough").
The critical-few framing echoes elegance and focus elsewhere in the corpus. Confidence 4.

gdc-l1-perf-0003 optimize the bottleneck — the critical few, not the trivial many performance bottleneck profiling diminishing-returns > performance work has sharply diminishing returns off the critical path. find the single biggest bottleneck, fix it, re-profile, and repeat. time spent speeding up code that isn't the bottleneck buys nothing — the frame is only as fast as its slowest necessary part. runtime is dominated by a small fraction of the code — knuth's "critical 3%" — so a game's frame time is gated by whichever system takes longest, and shaving a function that isn't that system changes the frame rate not at all [s-perf-profiling] [s-knuth-premature]. this makes optimization a targeting problem: the payoff comes from attacking the current top cost, not from broad, even effort across the codebase. and bottlenecks move — fix the top one and a different system becomes the new ceiling — which is why optimization is a loop (profile → fix the top cost → re-profile) rather than a single pass. working the loop concentrates every hour where it actually buys frame time. any optimization pass. the rule for what to optimize: whatever profiling currently shows as the largest cost on the critical path. death by a thousand cuts is real: sometimes there is no single fat bottleneck but many small costs (lots of tiny per-frame allocations, thousands of trivial draw calls), and the fix is a systemic pattern change rather than one hot function. frame-time spikes (hitches) also need different treatment than steady-state cost — a rare 40 ms stall hurts more than a slightly higher average. and memory or load-time budgets are separate axes from frame time. profile (perf-0001), fix the top cost, and immediately re-profile to find the new top cost — don't optimize a list of pre-planned targets, follow the profiler. watch for the many-small-costs pattern (attack it structurally). track spikes separately from averages. stop when the frame fits the budget (perf-0004), not when the code is "as fast as possible." little on "optimize the bottleneck"; the practical nuance is single-fat-bottleneck (attack it directly) vs. many-small-costs (change the pattern) vs. spikes (hunt the stall) — different shapes of performance problem needing different responses, all still guided by measurement. follows directly from perf-0001 (measure) and feeds perf-0004 (budget defines "fast enough"). the critical-few framing echoes elegance and focus elsewhere in the corpus. confidence 4.


A target frame rate is a fixed time budget — 60 fps means every frame must finish in about 16.6 ms. Treat that budget like money: allocate it across systems and hold each to its share. And know whether you're CPU-bound or GPU-bound, because the two have completely different fixes.

---
id: GDC-L1-PERF-0004
title: Budget the frame — decide what each system may spend
layer: L1
domain: PERF
subdomain: frame-budget
type: contextual
confidence: 4
status: canonical
tags:
  - performance
  - frame-budget
  - cpu-gpu-bound
  - platform-constraints
related:
  - GDC-L1-PERF-0001
  - GDC-L1-PERF-0003
  - GDC-L1-FEEL-0002
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-perf-profiling
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> A target frame rate is a **fixed time budget** — 60 fps means every frame must finish in
> about 16.6 ms. Treat that budget like money: allocate it across systems and hold each to
> its share. And know whether you're **CPU-bound or GPU-bound**, because the two have
> completely different fixes.

## Rationale
Frame rate isn't a vague "make it fast" goal; it's a hard deadline the game must hit every
frame or it stutters. Framing it as a budget makes the tradeoffs explicit — if rendering
takes 10 ms, AI, physics, gameplay, and audio must share the remaining ~6 ms — and turns
"is this affordable?" into a concrete question [S-perf-profiling]. The CPU/GPU distinction is
equally practical: the frame is bound by whichever finishes last, and the fixes diverge
sharply. CPU-bound → cut draw calls, batch/instance, reduce algorithmic work, pool objects;
GPU-bound → simplify shaders, add LODs, cull aggressively, scale resolution. Optimizing the
wrong side wastes effort (speeding up a GPU that's already waiting on the CPU changes
nothing). A quick diagnostic: halve the resolution — a big FPS jump means GPU-bound, little
change means CPU-bound.

## Applies when
Any real-time game with a frame-rate target — which is nearly all of them — and especially on
fixed hardware (console, mobile) where the budget is hard and known.

## Does not apply / Exceptions
Non-real-time or turn-based experiences have looser frame constraints. Targets vary by game
and platform (30 vs 60 vs 120+ fps; VR demands far stricter, per-eye budgets). Variable-rate
and frame-generation techniques complicate the simple "16.6 ms" model. And frame budget is
only one axis — memory and load-time budgets matter too, on their own terms.

## Implementation (kept separate from the principle)
Set a frame-time target and sub-budgets per system; profile against them (PERF-0001) and
treat an over-budget system as the bottleneck (PERF-0003). Determine CPU- vs GPU-bound early
(the resolution test) and aim fixes at the bound side. Budget to the *target* hardware, not
the dev machine. Remember that responsiveness (FEEL-0002) also depends on frame time —
performance is a feel issue, not just a technical one.

## Disagreement
Little on the budget concept itself; debate is about *what target* to choose (30 vs 60 vs
high-refresh, and the fidelity-vs-framerate tradeoff), which is a design/platform decision
rather than an engineering one.

## Notes
Turns PERF-0001/0003 into a concrete goal (fit the budget), and links performance to feel
(FEEL-0002 — latency and frame time are the same coin). Confidence 4.

gdc-l1-perf-0004 budget the frame — decide what each system may spend performance frame-budget cpu-gpu-bound platform-constraints > a target frame rate is a fixed time budget — 60 fps means every frame must finish in about 16.6 ms. treat that budget like money: allocate it across systems and hold each to its share. and know whether you're cpu-bound or gpu-bound, because the two have completely different fixes. frame rate isn't a vague "make it fast" goal; it's a hard deadline the game must hit every frame or it stutters. framing it as a budget makes the tradeoffs explicit — if rendering takes 10 ms, ai, physics, gameplay, and audio must share the remaining ~6 ms — and turns "is this affordable?" into a concrete question [s-perf-profiling]. the cpu/gpu distinction is equally practical: the frame is bound by whichever finishes last, and the fixes diverge sharply. cpu-bound → cut draw calls, batch/instance, reduce algorithmic work, pool objects; gpu-bound → simplify shaders, add lods, cull aggressively, scale resolution. optimizing the wrong side wastes effort (speeding up a gpu that's already waiting on the cpu changes nothing). a quick diagnostic: halve the resolution — a big fps jump means gpu-bound, little change means cpu-bound. any real-time game with a frame-rate target — which is nearly all of them — and especially on fixed hardware (console, mobile) where the budget is hard and known. non-real-time or turn-based experiences have looser frame constraints. targets vary by game and platform (30 vs 60 vs 120+ fps; vr demands far stricter, per-eye budgets). variable-rate and frame-generation techniques complicate the simple "16.6 ms" model. and frame budget is only one axis — memory and load-time budgets matter too, on their own terms. set a frame-time target and sub-budgets per system; profile against them (perf-0001) and treat an over-budget system as the bottleneck (perf-0003). determine cpu- vs gpu-bound early (the resolution test) and aim fixes at the bound side. budget to the target hardware, not the dev machine. remember that responsiveness (feel-0002) also depends on frame time — performance is a feel issue, not just a technical one. little on the budget concept itself; debate is about what target to choose (30 vs 60 vs high-refresh, and the fidelity-vs-framerate tradeoff), which is a design/platform decision rather than an engineering one. turns perf-0001/0003 into a concrete goal (fit the budget), and links performance to feel (feel-0002 — latency and frame time are the same coin). confidence 4.


On modern hardware, how data is laid out in memory frequently dominates performance more than how clever the code is. A cache miss costs hundreds of cycles while cache hits cost a few, so laying out hot data contiguously and touching it in order can beat micro-optimizing the instructions that touch it — often by multiples.

---
id: GDC-L1-PERF-0005
title: Respect data locality — memory layout often beats instruction cleverness
layer: L1
domain: PERF
subdomain: memory
type: contextual
confidence: 4
status: canonical
tags:
  - performance
  - data-locality
  - cache
  - data-oriented-design
  - memory
related:
  - GDC-L1-PERF-0001
  - GDC-L1-ARCH-0002
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-nystrom-gpp
  - S-perf-profiling
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> On modern hardware, *how data is laid out in memory* frequently dominates performance
> more than *how clever the code is*. A cache miss costs hundreds of cycles while cache hits
> cost a few, so laying out hot data contiguously and touching it in order can beat
> micro-optimizing the instructions that touch it — often by multiples.

## Rationale
Processors have gotten dramatically faster while main-memory latency has barely improved, so
the gap between a cache hit (a few cycles) and a main-memory fetch (hundreds) now dwarfs the
cost of most arithmetic [S-nystrom-gpp]. Code that chases pointers through scattered objects
stalls the CPU waiting on memory, no matter how tight the logic; code that streams through
contiguous arrays keeps the cache fed and the pipeline busy. Measured differences between
cache-friendly (structure-of-arrays) and cache-hostile (array-of-structures) layouts run
around 5–7× for hot iteration [S-perf-profiling]. This is why performance-critical systems
that iterate over many entities every frame (particles, physics, AI, ECS) care intensely
about layout — and why the fix for a slow hot loop is often "reorganize the data," not
"rewrite the math."

## Applies when
Hot loops over many items every frame — particles, physics, large entity updates, rendering
data. The more items and the more often you iterate, the more layout dominates.

## Does not apply / Exceptions
Cold code, small collections, and rarely-run logic don't benefit from layout gymnastics —
data-oriented restructuring adds real complexity and shouldn't be applied where profiling
(PERF-0001) doesn't show a memory-bound hot loop. This is where the "don't optimize
prematurely" rule (PERF-0002) bites: reorganizing everything into SoA up front is
over-engineering. Restructure the hot paths measurement identifies, not the whole codebase.

## Implementation (kept separate from the principle)
For memory-bound hot loops, prefer contiguous storage and sequential access; group the fields you touch together (hot/cold splitting; structure-of-arrays for the fields you iterate). Pool and reuse rather than scatter-allocate. Verify with the profiler that a loop is memory-bound before restructuring it.

## Disagreement
Data-oriented design (organize by data and access patterns for the cache) sits in tension
with classical object-oriented modeling and encapsulation (organize by conceptual objects) —
and with a naive reading of "composition over inheritance" (ARCH-0002), where scattered
component objects can be cache-hostile. The reconciliation most teams reach: **ECS**
(entity-component-*system*) gets both — composition's flexibility *and* data-oriented layout —
and you apply DOD to the hot paths while keeping OOP clarity for the cold majority. It's a
where-and-when tradeoff, not a war.

## Notes
Governed by PERF-0001 (measure first) and PERF-0002 (don't do it prematurely). Confidence 4.

gdc-l1-perf-0005 respect data locality — memory layout often beats instruction cleverness performance data-locality cache data-oriented-design memory > on modern hardware, how data is laid out in memory frequently dominates performance more than how clever the code is. a cache miss costs hundreds of cycles while cache hits cost a few, so laying out hot data contiguously and touching it in order can beat micro-optimizing the instructions that touch it — often by multiples. processors have gotten dramatically faster while main-memory latency has barely improved, so the gap between a cache hit (a few cycles) and a main-memory fetch (hundreds) now dwarfs the cost of most arithmetic [s-nystrom-gpp]. code that chases pointers through scattered objects stalls the cpu waiting on memory, no matter how tight the logic; code that streams through contiguous arrays keeps the cache fed and the pipeline busy. measured differences between cache-friendly (structure-of-arrays) and cache-hostile (array-of-structures) layouts run around 5–7× for hot iteration [s-perf-profiling]. this is why performance-critical systems that iterate over many entities every frame (particles, physics, ai, ecs) care intensely about layout — and why the fix for a slow hot loop is often "reorganize the data," not "rewrite the math." hot loops over many items every frame — particles, physics, large entity updates, rendering data. the more items and the more often you iterate, the more layout dominates. cold code, small collections, and rarely-run logic don't benefit from layout gymnastics — data-oriented restructuring adds real complexity and shouldn't be applied where profiling (perf-0001) doesn't show a memory-bound hot loop. this is where the "don't optimize prematurely" rule (perf-0002) bites: reorganizing everything into soa up front is over-engineering. restructure the hot paths measurement identifies, not the whole codebase. for memory-bound hot loops, prefer contiguous storage and sequential access; group the fields you touch together (hot/cold splitting; structure-of-arrays for the fields you iterate). pool and reuse rather than scatter-allocate. verify with the profiler that a loop is memory-bound before restructuring it. data-oriented design (organize by data and access patterns for the cache) sits in tension with classical object-oriented modeling and encapsulation (organize by conceptual objects) — and with a naive reading of "composition over inheritance" (arch-0002), where scattered component objects can be cache-hostile. the reconciliation most teams reach: ecs (entity-component-system) gets both — composition's flexibility and data-oriented layout — and you apply dod to the hot paths while keeping oop clarity for the cold majority. it's a where-and-when tradeoff, not a war. governed by perf-0001 (measure first) and perf-0002 (don't do it prematurely). confidence 4.


Match test rigor to risk

Spend testing effort where the risk is highest. Not everything needs the same rigor: the core loop, the systems everything depends on, the save/economy/networking that can corrupt or cheat, and the launch path deserve heavy testing; peripheral, low-impact, rarely-hit content deserves less. Test by risk, not uniformly.

---
id: GDC-L1-QA-0001
title: Match test rigor to risk
layer: L1
domain: QA
subdomain: test-strategy
type: contextual
confidence: 4
status: canonical
tags:
  - qa
  - testing
  - risk
  - strategy
  - prioritization
related:
  - GDC-L1-PERF-0003
  - GDC-L1-PROTO-0002
  - GDC-L1-QA-0005
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-games-user-research
  - S-scope-production
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> Spend testing effort where the risk is highest. Not everything needs the same rigor: the core
> loop, the systems everything depends on, the save/economy/networking that can corrupt or cheat,
> and the launch path deserve heavy testing; peripheral, low-impact, rarely-hit content deserves
> less. Test by risk, not uniformly.

## Rationale
Testing is finite, and applying it evenly wastes it — the same failure-hunting logic as
optimizing the bottleneck (PERF-0003) and prototyping the riskiest assumption first (PROTO-0002):
the payoff comes from attacking the highest (probability × impact) risks first [S-scope-production].
A save-corruption or economy-exploit bug is catastrophic and worth deep testing; a cosmetic glitch
in a rarely-visited room is not. Risk-based testing also directs *what kind* of testing to use
(QA-0002): high-regression-risk systems want automation, feel/fun questions want human play. A test
plan that ranks by risk finds the important bugs with the effort available, rather than exhausting
itself on the trivial and missing the catastrophic.

## Applies when
Any test planning — deciding what to test, how hard, and with what method. Throughout development
and especially before milestones and launch (SHIP-0001).

## Does not apply / Exceptions
Safety-, certification-, or compliance-critical areas may require uniform thoroughness regardless
of apparent risk (platform cert, legal, accessibility conformance). And "low risk" can be
mis-assessed — the point is *deliberate* risk assessment, not an excuse to skip testing you find
inconvenient. Very small games test informally but should still weight the core loop heaviest.

## Implementation (kept separate from the principle)
Rank areas by (likelihood of failure) × (cost if it fails), and allocate testing accordingly.
Test the core loop, dependency-heavy systems, and data-integrity/security/networking hardest.
Choose method by risk type: automation for regression-prone systems (QA-0002), human testing for
feel and emergent behavior. Re-assess risk as the game changes. Meet certification/compliance
thoroughness regardless.

## Disagreement
Risk-based testing (efficient, focuses effort — but depends on assessing risk correctly) vs.
uniform/exhaustive testing (thorough, but expensive and often infeasible). Certification contexts
demand uniformity; most development benefits from risk prioritization. The nuance is getting the
risk assessment right.

## Notes
The strategy principle of QA; the testing form of "attack the biggest risk first" (PERF-0003,
PROTO-0002). Confidence 4.

gdc-l1-qa-0001 match test rigor to risk qa testing risk strategy prioritization > spend testing effort where the risk is highest. not everything needs the same rigor: the core loop, the systems everything depends on, the save/economy/networking that can corrupt or cheat, and the launch path deserve heavy testing; peripheral, low-impact, rarely-hit content deserves less. test by risk, not uniformly. testing is finite, and applying it evenly wastes it — the same failure-hunting logic as optimizing the bottleneck (perf-0003) and prototyping the riskiest assumption first (proto-0002): the payoff comes from attacking the highest (probability × impact) risks first [s-scope-production]. a save-corruption or economy-exploit bug is catastrophic and worth deep testing; a cosmetic glitch in a rarely-visited room is not. risk-based testing also directs what kind of testing to use (qa-0002): high-regression-risk systems want automation, feel/fun questions want human play. a test plan that ranks by risk finds the important bugs with the effort available, rather than exhausting itself on the trivial and missing the catastrophic. any test planning — deciding what to test, how hard, and with what method. throughout development and especially before milestones and launch (ship-0001). safety-, certification-, or compliance-critical areas may require uniform thoroughness regardless of apparent risk (platform cert, legal, accessibility conformance). and "low risk" can be mis-assessed — the point is deliberate risk assessment, not an excuse to skip testing you find inconvenient. very small games test informally but should still weight the core loop heaviest. rank areas by (likelihood of failure) × (cost if it fails), and allocate testing accordingly. test the core loop, dependency-heavy systems, and data-integrity/security/networking hardest. choose method by risk type: automation for regression-prone systems (qa-0002), human testing for feel and emergent behavior. re-assess risk as the game changes. meet certification/compliance thoroughness regardless. risk-based testing (efficient, focuses effort — but depends on assessing risk correctly) vs. uniform/exhaustive testing (thorough, but expensive and often infeasible). certification contexts demand uniformity; most development benefits from risk prioritization. the nuance is getting the risk assessment right. the strategy principle of qa; the testing form of "attack the biggest risk first" (perf-0003, proto-0002). confidence 4.


Use the right kind of testing for the question. Automate what is deterministic and regression-prone — systems, math, save/load, builds — so it's checked cheaply and constantly. Use human testing for what machines can't judge: fun, feel, difficulty, and emergent behavior. Neither replaces the other.

---
id: GDC-L1-QA-0002
title: Automate regression; human-test feel and emergence
layer: L1
domain: QA
subdomain: automated-testing-of-games
type: contextual
confidence: 4
status: canonical
tags:
  - qa
  - automation
  - regression
  - playtesting
  - feel
related:
  - GDC-L1-PLAYTEST-0001
  - GDC-L1-QA-0001
  - GDC-L1-ARCH-0005
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-games-user-research
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> Use the right kind of testing for the question. **Automate** what is deterministic and
> regression-prone — systems, math, save/load, builds — so it's checked cheaply and constantly.
> Use **human testing** for what machines can't judge: fun, feel, difficulty, and emergent
> behavior. Neither replaces the other.

## Rationale
Games have two very different testing needs. Deterministic correctness (does the damage formula
compute right? does save/load round-trip? did that refactor break anything?) is perfect for
automation — fast, repeatable, and it catches regressions the moment they appear, which protects
iteration speed (ARCH-0005). But the questions that most determine whether a game is *good* — is
it fun, does it feel right, is the difficulty fair, what emerges when systems interact — are
subjective and situational, and only human play can answer them (which is why playtesting,
PLAYTEST-0001, exists) [S-games-user-research]. Trying to automate "is it fun" fails; trying to
manually regression-test every build wastes people and misses things. Matching method to question
(and to risk, QA-0001) gets both cheap regression safety and real judgment about the experience.

## Applies when
All testing. Automation scales with deterministic, regression-prone systems; human testing scales
with subjective/experiential and emergent aspects. Most games need both.

## Does not apply / Exceptions
Highly emergent or non-deterministic systems resist automated testing (and automating a fast-
changing prototype's tests can be wasted effort as it churns — automate *stable* things). Tiny
games may rely mostly on human testing. And automation has real setup/maintenance cost that must
be justified. The split is a guide, not a mandate to automate everything automatable.

## Implementation (kept separate from the principle)
Write automated tests for stable, deterministic, regression-prone systems (formulas, save/load,
core systems, build validation — CONTENT-0004/0005). Run them continuously (CONTENT-0005). Reserve
human testing — structured playtests (PLAYTEST) and exploratory QA — for feel, fun, difficulty,
and emergent/edge behavior. Prioritize both by risk (QA-0001).

## Disagreement
Test-automation-heavy (fast regression safety, but setup cost and can't judge fun) vs.
human-testing-heavy (judges the experience, but slow and misses regressions). The synthesis —
automate the deterministic, human-test the experiential — is broadly held; the debate is how much
to invest in automation for a medium where the most important qualities are subjective.

## Notes
The method principle of QA; pairs automation with human playtesting (PLAYTEST-0001) and protects
iteration (ARCH-0005) via regression safety. Confidence 4.

gdc-l1-qa-0002 automate regression; human-test feel and emergence qa automation regression playtesting feel > use the right kind of testing for the question. automate what is deterministic and regression-prone — systems, math, save/load, builds — so it's checked cheaply and constantly. use human testing for what machines can't judge: fun, feel, difficulty, and emergent behavior. neither replaces the other. games have two very different testing needs. deterministic correctness (does the damage formula compute right? does save/load round-trip? did that refactor break anything?) is perfect for automation — fast, repeatable, and it catches regressions the moment they appear, which protects iteration speed (arch-0005). but the questions that most determine whether a game is good — is it fun, does it feel right, is the difficulty fair, what emerges when systems interact — are subjective and situational, and only human play can answer them (which is why playtesting, playtest-0001, exists) [s-games-user-research]. trying to automate "is it fun" fails; trying to manually regression-test every build wastes people and misses things. matching method to question (and to risk, qa-0001) gets both cheap regression safety and real judgment about the experience. all testing. automation scales with deterministic, regression-prone systems; human testing scales with subjective/experiential and emergent aspects. most games need both. highly emergent or non-deterministic systems resist automated testing (and automating a fast- changing prototype's tests can be wasted effort as it churns — automate stable things). tiny games may rely mostly on human testing. and automation has real setup/maintenance cost that must be justified. the split is a guide, not a mandate to automate everything automatable. write automated tests for stable, deterministic, regression-prone systems (formulas, save/load, core systems, build validation — content-0004/0005). run them continuously (content-0005). reserve human testing — structured playtests (playtest) and exploratory qa — for feel, fun, difficulty, and emergent/edge behavior. prioritize both by risk (qa-0001). test-automation-heavy (fast regression safety, but setup cost and can't judge fun) vs. human-testing-heavy (judges the experience, but slow and misses regressions). the synthesis — automate the deterministic, human-test the experiential — is broadly held; the debate is how much to invest in automation for a medium where the most important qualities are subjective. the method principle of qa; pairs automation with human playtesting (playtest-0001) and protects iteration (arch-0005) via regression safety. confidence 4.


Reproduction is the heart of fixing bugs: a defect you can reliably trigger you can diagnose and verify fixed; one you can't reproduce you can only guess at. Invest in the things that make bugs reproducible — clear repro steps, determinism where feasible, good logging, and captured state — so bugs become tractable instead of haunting.

---
id: GDC-L1-QA-0003
title: A bug you can't reproduce, you can't fix
layer: L1
domain: QA
subdomain: repro-and-bug-tracking
type: contextual
confidence: 4
status: canonical
tags:
  - qa
  - reproduction
  - bug-tracking
  - determinism
  - logging
related:
  - GDC-L1-QA-0002
  - GDC-L1-CONTENT-0005
  - GDC-L1-TEAM-0003
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-games-user-research
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> Reproduction is the heart of fixing bugs: a defect you can reliably trigger you can diagnose and
> verify fixed; one you can't reproduce you can only guess at. Invest in the things that make bugs
> reproducible — clear repro steps, determinism where feasible, good logging, and captured state —
> so bugs become tractable instead of haunting.

## Rationale
The debugging loop is reproduce → diagnose → fix → verify, and it stalls entirely at step one: if
you can't make the bug happen on demand, you can't watch it, can't be sure of the cause, and can't
confirm your fix actually worked [S-games-user-research]. So reproducibility is the single most
valuable property for bug-fixing, and it doesn't happen by accident — it's enabled by disciplined
repro steps in reports, determinism (same inputs → same behavior, which also aids automated
testing, QA-0002, and reproducible builds, CONTENT-0005), comprehensive logging, and the ability
to capture and replay state. Non-reproducible bugs ("it happened once") are the ones that ship and
recur. Making bugs reproducible is upstream of fixing them.

## Applies when
All bug-fixing and QA. Especially critical for intermittent, timing-dependent, or emergent bugs,
and for anything that must be verified fixed.

## Does not apply / Exceptions
Some bugs are genuinely rare/environmental and full determinism is impractical (network races,
hardware-specific issues) — there you invest in *observability* (logging, crash dumps, telemetry)
to reconstruct what happened, since you can't reproduce it directly. And chasing perfect
reproducibility for a trivial cosmetic bug isn't worth it (risk-weight it, QA-0001).

## Implementation (kept separate from the principle)
Require clear repro steps in bug reports. Build for determinism where feasible (fixed seeds,
deterministic simulation) — it aids repro, automated testing (QA-0002), and reproducible builds
(CONTENT-0005). Log richly and capture state/crash dumps so hard-to-repro bugs can be reconstructed
(observability). Verify fixes by reproducing the original and confirming it's gone. Treat
non-reproducible recurring bugs as a signal to improve observability.

## Disagreement
Little on the principle; the nuance is how much to invest in determinism/observability infrastructure
versus living with some irreproducible bugs. High-reliability and competitive/networked games invest
heavily; smaller games lean on logging and accept some mystery bugs.

## Notes
The debugging-foundation principle of QA; enabled by determinism (shared with QA-0002 and
CONTENT-0005) and observability. Pairs with blameless problem-solving (TEAM-0003 — reproduce and
fix the system, don't blame). Confidence 4.

gdc-l1-qa-0003 a bug you can't reproduce, you can't fix qa reproduction bug-tracking determinism logging > reproduction is the heart of fixing bugs: a defect you can reliably trigger you can diagnose and verify fixed; one you can't reproduce you can only guess at. invest in the things that make bugs reproducible — clear repro steps, determinism where feasible, good logging, and captured state — so bugs become tractable instead of haunting. the debugging loop is reproduce → diagnose → fix → verify, and it stalls entirely at step one: if you can't make the bug happen on demand, you can't watch it, can't be sure of the cause, and can't confirm your fix actually worked [s-games-user-research]. so reproducibility is the single most valuable property for bug-fixing, and it doesn't happen by accident — it's enabled by disciplined repro steps in reports, determinism (same inputs → same behavior, which also aids automated testing, qa-0002, and reproducible builds, content-0005), comprehensive logging, and the ability to capture and replay state. non-reproducible bugs ("it happened once") are the ones that ship and recur. making bugs reproducible is upstream of fixing them. all bug-fixing and qa. especially critical for intermittent, timing-dependent, or emergent bugs, and for anything that must be verified fixed. some bugs are genuinely rare/environmental and full determinism is impractical (network races, hardware-specific issues) — there you invest in observability (logging, crash dumps, telemetry) to reconstruct what happened, since you can't reproduce it directly. and chasing perfect reproducibility for a trivial cosmetic bug isn't worth it (risk-weight it, qa-0001). require clear repro steps in bug reports. build for determinism where feasible (fixed seeds, deterministic simulation) — it aids repro, automated testing (qa-0002), and reproducible builds (content-0005). log richly and capture state/crash dumps so hard-to-repro bugs can be reconstructed (observability). verify fixes by reproducing the original and confirming it's gone. treat non-reproducible recurring bugs as a signal to improve observability. little on the principle; the nuance is how much to invest in determinism/observability infrastructure versus living with some irreproducible bugs. high-reliability and competitive/networked games invest heavily; smaller games lean on logging and accept some mystery bugs. the debugging-foundation principle of qa; enabled by determinism (shared with qa-0002 and content-0005) and observability. pairs with blameless problem-solving (team-0003 — reproduce and fix the system, don't blame). confidence 4.


The dev machine lies. Test on the target hardware and under real conditions — the platforms players use, real content volumes, long play sessions (soak), heavy load (stress), poor networks, and the certification requirements the game must pass. Problems that never appear in the studio appear constantly in the wild.

---
id: GDC-L1-QA-0004
title: Test on target hardware and under real conditions
layer: L1
domain: QA
subdomain: soak-and-stress
type: contextual
confidence: 4
status: canonical
tags:
  - qa
  - target-hardware
  - soak
  - stress
  - certification
  - real-conditions
related:
  - GDC-L1-PERF-0004
  - GDC-L1-PLAYTEST-0006
  - GDC-L1-QA-0001
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-games-user-research
  - S-scope-production
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> The dev machine lies. Test on the **target hardware** and under **real conditions** — the
> platforms players use, real content volumes, long play sessions (soak), heavy load (stress),
> poor networks, and the certification requirements the game must pass. Problems that never appear
> in the studio appear constantly in the wild.

## Rationale
Development happens on powerful, clean, well-connected machines running short sessions — conditions
nothing like where the game actually ships [S-games-user-research] [S-scope-production]. Whole
classes of defects only surface off the dev box: performance and memory problems on
minimum-spec/console/mobile hardware (a frame-budget reality, PERF-0004), memory leaks and state
corruption over long **soak** sessions, breakage under **stress** (many entities, full servers),
failures on bad networks, and platform-**certification** violations that block release. Testing
only where you develop is a form of the sampling bias that skews playtests (PLAYTEST-0006):
the dev environment is an unrepresentative sample of the shipping environment. Testing on target,
at scale, and over time is how you catch the bugs that would otherwise be discovered by players at
launch (SHIP-0001).

## Applies when
Throughout development, intensively before launch (SHIP-0001) — anything with fixed target
hardware (console, mobile, VR), long sessions, networking, or platform certification.

## Does not apply / Exceptions
Early prototypes on a single dev platform can defer target testing (but shouldn't defer it
*forever* — the longer you wait, the nastier the surprises). Single-platform PC games have a
narrower target range. Certification only applies to platforms that require it. Scale the effort to
the platforms and conditions the game will actually meet.

## Implementation (kept separate from the principle)
Test regularly on minimum-spec and each target platform, not just the dev machine. Run soak tests (long sessions, watch for leaks/degradation) and stress tests (peak load). Test on realistic networks (latency, loss) for multiplayer (MP-0004). Verify certification/compliance requirements early. Fold this into the launch-readiness plan (SHIP-0001).

## Disagreement
Little on the principle; the nuance is how early and how often to test on target (target hardware
and cert kits cost money and time) vs. developing fast on dev machines. Console/mobile/VR force
early target testing; PC-only games have more slack. Risk-weight it (QA-0001).

## Notes
The real-conditions principle of QA; connects to performance budgeting on target (PERF-0004),
sampling representativeness (PLAYTEST-0006), and launch readiness (SHIP-0001). Confidence 4.

gdc-l1-qa-0004 test on target hardware and under real conditions qa target-hardware soak stress certification real-conditions > the dev machine lies. test on the target hardware and under real conditions — the platforms players use, real content volumes, long play sessions (soak), heavy load (stress), poor networks, and the certification requirements the game must pass. problems that never appear in the studio appear constantly in the wild. development happens on powerful, clean, well-connected machines running short sessions — conditions nothing like where the game actually ships [s-games-user-research] [s-scope-production]. whole classes of defects only surface off the dev box: performance and memory problems on minimum-spec/console/mobile hardware (a frame-budget reality, perf-0004), memory leaks and state corruption over long soak sessions, breakage under stress (many entities, full servers), failures on bad networks, and platform-certification violations that block release. testing only where you develop is a form of the sampling bias that skews playtests (playtest-0006): the dev environment is an unrepresentative sample of the shipping environment. testing on target, at scale, and over time is how you catch the bugs that would otherwise be discovered by players at launch (ship-0001). throughout development, intensively before launch (ship-0001) — anything with fixed target hardware (console, mobile, vr), long sessions, networking, or platform certification. early prototypes on a single dev platform can defer target testing (but shouldn't defer it forever — the longer you wait, the nastier the surprises). single-platform pc games have a narrower target range. certification only applies to platforms that require it. scale the effort to the platforms and conditions the game will actually meet. test regularly on minimum-spec and each target platform, not just the dev machine. run soak tests (long sessions, watch for leaks/degradation) and stress tests (peak load). test on realistic networks (latency, loss) for multiplayer (mp-0004). verify certification/compliance requirements early. fold this into the launch-readiness plan (ship-0001). little on the principle; the nuance is how early and how often to test on target (target hardware and cert kits cost money and time) vs. developing fast on dev machines. console/mobile/vr force early target testing; pc-only games have more slack. risk-weight it (qa-0001). the real-conditions principle of qa; connects to performance budgeting on target (perf-0004), sampling representativeness (playtest-0006), and launch readiness (ship-0001). confidence 4.


Quality is a process, not a final gate. Catch defects as early as possible — at authoring (validate content, CONTENT-0004), at commit (automated tests, QA-0002), in review — rather than relying on a QA pass at the end to find everything. A bug caught the day it's made is cheap; the same bug found at launch is expensive or unshippable.

---
id: GDC-L1-QA-0005
title: Build quality in — don't test it in at the end
layer: L1
domain: QA
subdomain: test-strategy
type: contextual
confidence: 4
status: canonical
tags:
  - qa
  - shift-left
  - quality
  - process
  - prevention
related:
  - GDC-L1-TEAM-0003
  - GDC-L1-CONTENT-0004
  - GDC-L1-PROD-0004
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-games-user-research
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> Quality is a *process*, not a final gate. Catch defects as early as possible — at authoring
> (validate content, CONTENT-0004), at commit (automated tests, QA-0002), in review — rather than
> relying on a QA pass at the end to find everything. A bug caught the day it's made is cheap; the
> same bug found at launch is expensive or unshippable.

## Rationale
The cost of a defect rises steeply the longer it goes undetected: caught at authoring it's a quick
edit; caught in a milestone build it's a bug hunt; caught by players at launch it's a crisis and a
reputation hit (SHIP-0001) [S-games-user-research]. Treating QA as only an end-phase gate
guarantees that defects accumulate cheaply-fixable-but-uncaught until they're expensive — so the
better strategy is to push quality *upstream* ("shift left"): validate data on ingest
(CONTENT-0004), run automated regression continuously (QA-0002), review changes, and make it safe
to surface problems early (the blameless, learn-from-failure culture of TEAM-0003). This also
demands that schedules *budget* for quality throughout rather than assuming a magic QA phase at the
end (PROD-0004). Building quality in makes the final QA a confirmation, not a rescue.

## Applies when
The whole development process — quality practices belong at every stage, not just before launch.

## Does not apply / Exceptions
A dedicated QA/hardening phase near launch is still valuable and necessary — "build quality in"
complements it, it doesn't replace it. And prototypes deliberately run rough (quality-in would be
premature polish on throwaway work, PROTO-0004). The principle is about not *deferring all* quality
to the end, not about polishing prototypes.

## Implementation (kept separate from the principle)
Push defect-catching upstream: validate content at ingest (CONTENT-0004), automate regression tests
run on every change (QA-0002, CONTENT-0005), review code and design, and playtest early and often
(PLAYTEST-0002). Make surfacing problems safe and blameless (TEAM-0003). Budget for quality
throughout the schedule (PROD-0004), not as a final phase alone. Use the end-phase QA to confirm,
not to discover everything.

## Disagreement
Shift-left/quality-as-process (cheaper defects, less end-crunch — but requires upstream discipline
and tooling) vs. quality-as-final-gate (simpler process, defer QA cost — but expensive late defects
and launch risk). Modern practice favors building quality in; the debate is how much upstream
investment a given project can justify.

## Notes
The prevention/process principle of QA; unifies content validation (CONTENT-0004), automated
regression (QA-0002), blameless learning (TEAM-0003), and quality-budgeted scheduling (PROD-0004).
Confidence 4.

gdc-l1-qa-0005 build quality in — don't test it in at the end qa shift-left quality process prevention > quality is a process, not a final gate. catch defects as early as possible — at authoring (validate content, content-0004), at commit (automated tests, qa-0002), in review — rather than relying on a qa pass at the end to find everything. a bug caught the day it's made is cheap; the same bug found at launch is expensive or unshippable. the cost of a defect rises steeply the longer it goes undetected: caught at authoring it's a quick edit; caught in a milestone build it's a bug hunt; caught by players at launch it's a crisis and a reputation hit (ship-0001) [s-games-user-research]. treating qa as only an end-phase gate guarantees that defects accumulate cheaply-fixable-but-uncaught until they're expensive — so the better strategy is to push quality upstream ("shift left"): validate data on ingest (content-0004), run automated regression continuously (qa-0002), review changes, and make it safe to surface problems early (the blameless, learn-from-failure culture of team-0003). this also demands that schedules budget for quality throughout rather than assuming a magic qa phase at the end (prod-0004). building quality in makes the final qa a confirmation, not a rescue. the whole development process — quality practices belong at every stage, not just before launch. a dedicated qa/hardening phase near launch is still valuable and necessary — "build quality in" complements it, it doesn't replace it. and prototypes deliberately run rough (quality-in would be premature polish on throwaway work, proto-0004). the principle is about not deferring all quality to the end, not about polishing prototypes. push defect-catching upstream: validate content at ingest (content-0004), automate regression tests run on every change (qa-0002, content-0005), review code and design, and playtest early and often (playtest-0002). make surfacing problems safe and blameless (team-0003). budget for quality throughout the schedule (prod-0004), not as a final phase alone. use the end-phase qa to confirm, not to discover everything. shift-left/quality-as-process (cheaper defects, less end-crunch — but requires upstream discipline and tooling) vs. quality-as-final-gate (simpler process, defer qa cost — but expensive late defects and launch risk). modern practice favors building quality in; the debate is how much upstream investment a given project can justify. the prevention/process principle of qa; unifies content validation (content-0004), automated regression (qa-0002), blameless learning (team-0003), and quality-budgeted scheduling (prod-0004). confidence 4.


The purpose of a prototype is to find the fun as fast as possible. Before investing in content, art, story, or supporting systems, build the smallest playable thing that answers "is the core actually fun?" If the fun isn't there in the prototype, it will not appear later with polish.

---
id: GDC-L1-PROTO-0001
title: Find the fun first — prove the core before building around it
layer: L1
domain: PROTO
subdomain: prototyping
type: objective
confidence: 4
status: canonical
tags:
  - prototyping
  - find-the-fun
  - core-loop
  - iteration
  - vertical-slice
related:
  - GDC-L1-SYS-0001
  - GDC-L1-DESIGN-0001
  - GDC-L1-PROTO-0006
depends_on: []
conflicts_with: []
supersedes: []
sources:
  - S-proto-vertical-slice
  - S-schell-artofgamedesign
first_added: 2026-07-14
last_verified: 2026-07-14
---

## Statement
> The purpose of a prototype is to **find the fun as fast as possible.** Before investing
> in content, art, story, or supporting systems, build the smallest playable thing that
> answers "is the core actually fun?" If the fun isn't there in the prototype, it will not
> appear later with polish.

## Rationale
Fun lives in the core loop (SYS-0001), and whether that loop is fun is an empirical
question only play can answer (DESIGN-0001) — so the cheapest, fastest way to a good game
is to test the core in isolation before anything is built on it. Polish, content, and art
amplify a fun core; they cannot create one. Teams that build the game *around* an untested
core routinely discover, months and a fortune later, that the thing at the center was never
fun — a discovery a week-one prototype would have delivered for almost nothing. "Find the
fun first" front-loads the one risk that can sink everything.

## Applies when
The start of any project or major feature, and whenever the fundamental question is "is
this fun?" rather than "how do we polish it?"

## Does not apply / Exceptions
Some experiences aren't "fun" in the moment-to-moment sense — narrative, atmospheric, or
contemplative games seek a different core value (tension, meaning, mood), and the prototype
should target *that* value instead. And a few qualities can't be judged in a bare
prototype: feel and mood partly depend on fidelity (see PROTO-0003). "Find the fun" then
generalizes to "prove the core value early," whatever that value is.

## Implementation (kept separate from the principle)
Build the core loop in greybox with no content (PROTO-0003), aim it at the riskiest
assumption (PROTO-0002), and put it in front of players immediately (PLAYTEST-0002). Judge
by whether it's compelling for a few minutes with nothing else attached. Note the related
distinction: a *prototype* answers "*should* we make this game?"; a *vertical slice* (a
polished small demo at final quality) answers "*can* we make it?" — don't conflate the two,
and don't polish while you're still finding the fun.

## Disagreement
Broad agreement that the core must be proven early; the nuance is which *value* to prove
for non-"fun" games, and how much fidelity a fair test of the core requires (PROTO-0003).

## Notes
The keystone of the PROTO domain and the practical front-end of SYS-0001 (perfect the core
loop) and DESIGN-0001 (judge by the experience). Powered by the iteration loop (PROTO-0006).
Confidence 4.

gdc-l1-proto-0001 find the fun first — prove the core before building around it prototyping find-the-fun core-loop iteration vertical-slice > the purpose of a prototype is to find the fun as fast as possible. before investing in content, art, story, or supporting systems, build the smallest playable thing that answers "is the core actually fun?" if the fun isn't there in the prototype, it will not appear later with polish. fun lives in the core loop (sys-0001), and whether that loop is fun is an empirical question only play can answer (design-0001) — so the cheapest, fastest way to a good game is to test the core in isolation before anything is built on it. polish, content, and art amplify a fun core; they cannot create one. teams that build the game around an untested core routinely discover, months and a fortune later, that the thing at the center was never fun — a discovery a week-one prototype would have delivered for almost nothing. "find the fun first" front-loads the one risk that can sink everything. the start of any project or major feature, and whenever the fundamental question is "is this fun?" rather than "how do we polish it?" some experiences aren't "fun" in the moment-to-moment sense — narrative, atmospheric, or contemplative games seek a different core value (tension, meaning, mood), and the prototype should target that value instead. and a few qualities can't be judged in a bare prototype: feel and mood partly depend on fidelity (see proto-0003). "find the fun" then generalizes to "prove the core value early," whatever that value is. build the core loop in greybox with no content (proto-0003), aim it at the riskiest assumption (proto-0002), and put it in front of players immediately (playtest-0002). judge by whether it's compelling for a few minutes with nothing else attached. note the related distinction: a prototype answers "should we make this game?"; a vertical slice (a polished small demo at final quality) answers "can we make it?" — don't conflate the two, and don't polish while you're still finding the fun. broad agreement that the core must be proven early; the nuance is which value to prove for non-"fun" games, and how much fidelity a fair test of the core requires (proto-0003). the keystone of the proto domain and the practical front-end of sys-0001 (perfect the core loop) and design-0001 (judge by the experience). powered by the iteration loop (proto-0006). confidence 4.