How to Convert to snake_case (and When Not To)
snake_case joins lowercase words with single underscores, as in user_profile. Python variables and functions, Postgres column names, and YAML or env keys mostly follow it.
Open the tool:snake_case Converter
When underscores are the right choice
The usual case is a split stack: the JavaScript side sends userName, the Python backend and its columns say user_name, and something has to map between them. Naming tables, writing ORM models and tidying config keys all go faster when the batch is converted to underscores first, because the mapping layer then has fewer special cases.
The other case is normalising inherited names. Exports from older systems arrive with capitals, spaces and hyphens mixed together, which is awkward in both SQL and ORM code. Converting to lowercase with underscores and stripping the punctuation at least makes the queries and migration scripts predictable.
- Python variables, functions and module names
- Database columns and index names such as user_id
- YAML, env and config file keys
- Normalising mixed-case headers from legacy exports
What gets split and what gets merged
It does one thing camelCase does not: split on the boundary between a lowercase letter or digit and an uppercase letter, then lowercase everything, collapse runs of non-alphanumeric characters into one underscore, and trim underscores at both ends. So userProfile becomes user_profile, which the camelCase converter cannot do.
Two details matter. Repeated separators merge into one, so a b and a--b both give a_b with no empty segment. Digits stay attached, so version2 remains version2 rather than being split. Chinese characters are alphanumeric by no definition used here and are dropped, so translate first if the meaning has to survive.
- Camel boundaries are split: userProfile → user_profile
- Repeated separators merge, no empty segments
- Leading and trailing underscores are trimmed
- Digits are not split: version2 stays as is
- Chinese characters are dropped — translate first
Where it does not belong
URL paths and CSS class names generally take hyphens rather than underscores. Google treats hyphens as word separators and does not treat underscores that way, so /user-profile is parsed into words where /user_profile is not, and CSS has long treated hyphens as the norm. Use the kebab-case converter when the output is a link or a class.
Two things the tool cannot do for you: avoid reserved words — order, user and class usually need quoting as column names — and avoid Python's double-underscore names such as __init__ and __str__, which carry language-level meaning rather than acting as plain separators. Run the result through the real CREATE TABLE or code path before trusting it.
- URLs and CSS: hyphens, not underscores
- Reserved words such as order or user need quoting
- Do not generate __x__ style double-underscore names
- Test in the real statement before committing
FAQ
Should I use snake_case or kebab-case?
It depends on where the name lives. Variables, database columns and config keys take snake_case; URL paths, CSS classes and file names take kebab-case. Hyphens are the convention in URLs and CSS, while underscores are legal inside identifiers in most programming languages.
Why do database column names usually use lowercase with underscores?
Because unquoted identifiers are handled inconsistently across databases — Postgres folds them to lowercase — so mixed case forces double quotes everywhere. Lowercase with underscores removes that problem and keeps SQL, ORM models and query results spelled the same way.
Are repeated underscores kept?
No. Runs of non-alphanumeric characters collapse into a single underscore, so a___b and a b both become a_b with no empty segment. Underscores at the start and end are trimmed, while single underscores in the middle stay where they were.
Related tool:snake_case Converter