Storing third-party API keys and OAuth tokens in a database is unavoidable for most SaaS backends, but storing them as plaintext is a liability the moment a database backup leaks. AES-256-GCM gives you authenticated encryption with a small, well-understood API surface — this post walks through a production-ready Go pattern for encrypting secrets at rest, plus the mistakes that quietly break it.

Why GCM instead of CBC

AES-CBC needs a separate MAC to detect tampering, and it's easy to forget that step or implement it incorrectly (padding-oracle bugs are a classic result). AES-GCM is an authenticated encryption mode: it produces ciphertext and an authentication tag in one pass, so any bit-flip in storage or transit fails decryption loudly instead of silently. For secrets at rest, that fail-loud property is exactly what you want.

The pattern

The shape that holds up in production is: derive a 32-byte key once, generate a fresh random nonce per encryption call, and prepend the nonce to the ciphertext so you never have to store it separately.