Quick answer: API keys, store credentials, signing keys, and webhook URLs never belong in version control — once committed, they live in history forever and must be rotated, not just deleted. The pattern: secrets in environment files that are gitignored (with a committed .example template), CI secrets in the platform's secret store, and the hard truth that anything shipped inside the game client isn't secret at all.

API keys, store credentials, signing keys, and webhook URLs never belong in version control — once committed, they live in history forever and must be rotated, not just deleted. The pattern: secrets in environment files that are gitignored (with a committed .example template), CI secrets in the platform's secret store, and the hard truth that anything shipped inside the game client isn't secret at all. That's the short version — the sections below get into the how, the why, and the mistakes worth dodging.

What counts, and why deletion doesn't fix leaks

The secret list is longer than it feels: backend API keys, Steamworks/console credentials, signing certificates and keystores, analytics and crash-reporting write keys (lower stakes, still worth hygiene), webhook URLs, and any third-party service token. Once pushed, a secret is in clone history permanently — scrapers harvest public repos in minutes, and history rewrites are unreliable cleanup. The only real remediation is rotation: revoke, reissue, then clean.

Private repos soften but don't remove the risk: collaborators, leaked laptops, and the eventual open-sourcing you didn't plan for all inherit history.

The boring pattern that works

Project secrets live in a .env (or equivalent config) that's in .gitignore from the very first commit, alongside a committed .env.example listing every needed variable with dummy values — onboarding documentation and leak prevention in one file. Build scripts and the game's tooling read from environment, never from literals in code.

CI gets its own channel: every platform (GitHub Actions and kin) has an encrypted secrets store injected at runtime — store upload credentials and signing keys there, and they exist in neither repo nor logs. Add a pre-commit secret scanner (several free ones) as the cheap last line.

The client is enemy territory

Anything inside the shipped game — strings in code, config files, 'hidden' assets — is extractable by any motivated teenager with a hex editor; obfuscation only sets the difficulty slider. Design accordingly: keys that ship with the client must be harmless-if-public (write-only telemetry keys, public identifiers), and anything powerful (purchases, leaderboard writes you care about, admin operations) belongs behind a server you control that holds the real secrets.

This is an architecture decision masquerading as a security tip: 'what can the client be trusted with' decided early shapes the whole backend honestly; decided late, it ships as an incident.

Automate the step you dread

Whatever release step you dread — building all platforms, uploading to Steam, updating version numbers — is the step you'll postpone, and postponed releases mean slower fixes and staler feedback. Dread is a signal: that step wants a script.

You don't need a DevOps team. One shell script that builds and uploads is 90% of the value. Each manual step you remove makes shipping a small patch feel routine instead of risky — and teams that patch easily, patch often.

Your future self is a stranger — leave notes

Six months from now you will not remember why that magic number is 0.73 or which scene is safe to delete. Project knowledge that lives only in your head evaporates on contact with a break, a jam, or a day job crunch.

Keep one running NOTES file: decisions made, things that look unused but aren't, how to do the fiddly release steps. Five minutes of writing per week buys you days of re-discovery later.

The quiet work that protects all of this

Everything in this post gets undone by an unstable build. A great store page, a clever marketing beat, a perfect jam entry — none of it survives 'crashed twice, refunded'. Stability isn't a feature players praise, but it's the floor everything else stands on.

Give yourself visibility before you need it: crash reports with stack traces, a simple way for players to flag issues from inside the game, and a habit of fixing the top recurring error before adding anything new.

Putting it to work

Don't try to act on all of this at once. Pick the one change that costs you the least and pays the most this week, do it, and see what actually happens before reaching for the next.

Most of this rewards steadiness over intensity. A small improvement made every week, checked against how real players respond, outruns any single burst of effort — in this corner of game development and every other one.

If your machine died tonight, you should be working again by morning. Build toward that.