S3 + DynamoDB is the right call, yeah. But honestly, the real win is splitting state by environment and team boundary, not just throwing everything behind locking. We run separate state files per service per environment. Makes rollbacks way less scary and keeps blast radius small.
One thing I'd add: lock timeout tuning matters more than people think. Set it too high and a crashed CI job blocks everyone for hours. We use 30s with exponential backoff. Also, encrypt that state file at rest. S3 encryption is free.