Quick answer: Enter a code freeze at least 2-4 weeks before your launch date. During this period, no new features are added; only bug fixes are committed. The exact timing depends on your game's complexity, but 2 weeks is the minimum for a small indie game, and 4 weeks is safer for larger projects.

Learning how to reduce bug count before game launch is a common challenge for game developers. Launch day is a one-way door. The impression your game makes in its first 48 hours on a storefront determines its trajectory more than almost any other factor. Negative reviews about crashes and bugs are hard to recover from, even with patches. The weeks before launch are your last chance to find and fix the issues that would tank your game’s reception, and most indie developers do not use that time effectively.

The Code Freeze: Drawing the Line

A code freeze is the single most effective practice for reducing bugs before launch. During a code freeze, no new features are added. The only commits allowed are bug fixes, and even those should be reviewed carefully because every change carries the risk of introducing a new issue.

For indie games, a 2-4 week freeze before launch is realistic. During that window, the entire team shifts from feature development to bug finding and fixing. The temptation to sneak in “one more feature” is strong, but every feature added after the freeze creates untested surface area that may not get sufficient QA before launch.

# Git branch strategy during code freeze
# Only bugfix branches merge into the release branch

# Create the release branch at the start of code freeze
$ git checkout -b release/1.0 main

# All bug fixes branch from and merge into the release branch
$ git checkout -b fix/save-corruption release/1.0
# ... fix the bug ...
$ git checkout release/1.0
$ git merge fix/save-corruption

# Feature work continues on main but does NOT merge into release
$ git checkout main
$ git checkout -b feature/new-boss
# This waits for post-launch update

# After launch, merge release fixes back to main
$ git checkout main
$ git merge release/1.0

The branch strategy above keeps feature work separated from bug fixes. Developers who finish their bug assignments can start on post-launch features without affecting the release branch. This removes the pressure to merge unrelated changes and keeps the release branch stable.

Focused Testing Passes

Casual playtesting finds casual bugs. To find the bugs that matter — crashes, progression blockers, data corruption — you need structured testing passes that systematically exercise critical paths.

A testing pass is a dedicated session where you test one specific area of the game with the explicit goal of finding bugs in that area. You are not playing the game for fun. You are actively trying to break it. Here are the testing passes every game needs before launch:

First-time user experience (FTUE) pass. Start a brand new save file and play through the first 30 minutes exactly as a new player would. Test the tutorial, the initial options, the first save. This is what every player and every reviewer will experience first. A bug here is ten times more damaging than a bug in endgame content.

Critical path pass. Play through the entire main progression from start to finish, touching every required quest, boss fight, and story beat. This is the minimum content that every player will experience if they finish the game. Every step of this path must work.

Save/load pass. Save at every significant point in the game and reload. Save before boss fights, during cutscenes, at shop screens, during dialogue. Quit the game and restart from each save. Verify that game state is fully preserved. Save corruption is one of the most damaging bugs a game can ship with.

Platform requirements pass. Verify every platform-specific requirement: controller remapping on consoles, touch controls on mobile, Steam Deck compatibility if you support it, minimum spec hardware testing on PC. Each platform has unique failure modes that only manifest on that platform.

# Automated smoke test script
# Run this on every build during code freeze
# Verifies the game launches and basic systems work

#!/bin/bash
set -e

echo "=== Smoke Test Suite ==="

# Test 1: Game launches without crash
echo "[1/5] Testing game launch..."
timeout 30 ./game --headless --quit-after-frames=60
echo "  PASS: Game launched and ran 60 frames"

# Test 2: New save file can be created
echo "[2/5] Testing new save creation..."
timeout 30 ./game --headless --test-new-save
echo "  PASS: New save created successfully"

# Test 3: Existing save file loads correctly
echo "[3/5] Testing save load..."
timeout 30 ./game --headless --test-load-save=test_save.sav
echo "  PASS: Save loaded without errors"

# Test 4: All scenes load without errors
echo "[4/5] Testing scene loading..."
timeout 120 ./game --headless --test-load-all-scenes
echo "  PASS: All scenes loaded"

# Test 5: Audio system initializes
echo "[5/5] Testing audio init..."
timeout 15 ./game --headless --test-audio-init
echo "  PASS: Audio initialized"

echo "=== All smoke tests passed ==="

Automated Testing for Indie Games

Automated tests sound like overkill for a small studio, but even a minimal set of automated tests catches regressions that slip through manual testing. The goal is not full test coverage. It is catching the catastrophic failures automatically so manual testing can focus on gameplay quality.

The highest-value automated tests for games are:

Launch test: Does the game start without crashing? Run this on every build, on every platform. A build that does not launch is the worst possible bug, and it is also the easiest to catch automatically.

Save/load round-trip test: Create a save file with known state, save it, load it, and verify the state matches. This catches serialization bugs that are notoriously hard to find through manual testing because they only manifest when specific game state is loaded.

Critical calculation tests: Unit tests for damage formulas, economy systems, progression curves, and any other math-driven system. A rounding error in your damage formula might go unnoticed during playtesting but cause rage among players who notice their level 50 character hits weaker than their level 49 one.

The Playtester Program

Your team has been playing the game for months or years. You have developed blindness to entire categories of bugs because you unconsciously avoid the steps that trigger them. Fresh eyes find bugs that experienced eyes cannot.

A structured playtester program during the pre-launch period brings in 10-50 external players who experience the game for the first time. They will try things your team never thought to try: using items in the wrong order, visiting areas out of sequence, mashing buttons during transitions, and generally playing the game in ways that feel wrong to you but represent how real players behave.

To make a playtester program effective:

Lower the reporting friction to near zero. Do not ask playtesters to fill out detailed forms. Provide an in-game reporting button that captures a screenshot and basic context automatically. Bugnet’s SDK provides exactly this — players press a key, type a sentence, and the report arrives in your dashboard with the screenshot, scene, platform, and game version filled in automatically.

Give testers specific missions. Instead of “play the game and report bugs,” give each tester a specific area or flow to focus on. “Play through chapter 2 and try to break the stealth system.” “Use every item in the shop on every enemy type.” Specific missions produce more thorough coverage than open-ended play.

Diversity of hardware is more valuable than quantity of testers. Ten testers with ten different hardware configurations will find more bugs than fifty testers all using similar gaming PCs. Actively recruit testers with low-end hardware, unusual peripherals, and non-English system locales.

“Every bug found before launch is a negative review prevented. The math is simple: ten hours of pre-launch testing saves a hundred hours of post-launch damage control.”

The Bug Burn-Down

During the code freeze, track your bug count daily. Plot the number of open P0 and P1 bugs over time. This burn-down chart tells you whether you are converging toward a launchable state or falling behind.

A healthy burn-down shows the total open bug count decreasing consistently, with new bugs arriving slower than old bugs are being fixed. If the line is flat or rising, you are not making progress — either the bug fix rate needs to increase or the launch date needs to move.

The critical metric is the P0 + P1 count. This must reach zero before launch. You can ship with P2 and P3 bugs. You should not ship with any P0 or P1 bugs. If you reach your launch date with unresolved P0s, delay. The cost of a delayed launch is always less than the cost of launching with critical bugs.

The Final 48 Hours

In the last two days before launch, stop fixing bugs except for genuine P0 emergencies. Every change you make at this point is a risk. A last-minute fix that introduces a new crash is worse than the original bug you were trying to fix.

Use the final 48 hours for full playthroughs on the release build. Do not build from source during this period. Play the exact binary that will ship to players. If it crashes, fix the crash and start the 48-hour clock again.

Related Issues

For specific strategies to improve your crash-free rate before launch, see how to reduce your game’s crash rate before launch. To build a comprehensive QA checklist for your release, read how to build a QA checklist for game release. And for regression testing strategies that prevent fixed bugs from coming back, check out regression testing strategies for indie games.

Code freeze is not a punishment. It is a gift: time to polish without the pressure of new features. Use it well.