Nobody argues about naming conventions because the conventions are interesting. They argue because a codebase with three of them is measurably harder to read, and because the arguments happen at exactly the moment everyone is tired — during review, about a variable, in a pull request that was supposed to be about something else.
The useful version of this topic is not which case is better. It is: which case belongs where, what happens where two conventions meet, and how to convert between them without breaking anything.
Where each convention actually lives
These are conventions, not rules, but they are conventions with heavy weight behind them — style guides, linters, and the standard libraries themselves.
- camelCase — variables and functions in JavaScript, Java, Swift, Kotlin, and C#'s locals.
- PascalCase — classes and types nearly everywhere, React components, and in Go the marker for an exported identifier rather than a stylistic choice.
- snake_case — variables and functions in Python and Ruby, and the default for SQL columns and table names.
- CONSTANT_CASE — environment variables, compile-time constants, and configuration keys.
- kebab-case — URLs, CSS class names and custom properties, HTML attributes, npm package names, and file names in most web projects.
Two of these are more than taste. In Go, capitalising the first letter is what makes something visible outside its package. And most SQL databases fold unquoted identifiers to a single case, which is why userName as a column name tends to come back as username and quietly stops matching your code — snake_case sidesteps the problem entirely.
Kebab-case in URLs is a similar practicality: hyphens are treated as word separators by search engines in a way underscores historically were not, and a hyphenated path is easier to read aloud over a phone.
The place it actually goes wrong: the boundary
Inside one language, everybody follows the local convention and nothing bad happens. The trouble starts where two systems meet — a Python API returning created_at to a TypeScript frontend that wants createdAt, or a database column feeding an object property.
The failure mode is not choosing wrong. It is converting in a dozen scattered places, so that half the codebase deals in one shape and half in the other and every function has to know which half it is in.
Do it once, at the edge. Convert in the serialisation layer or the API client, so that everything inside the boundary uses one convention and everything crossing it is transformed at a single point you can find later. Then write down which side is which, because the next person cannot guess.
Where the boundary is not yours to define — a third-party API — mirror their shape exactly in the layer that talks to them, and convert on the way into your own types. Renaming their fields halfway makes their documentation useless to you.
Acronyms, the argument you can end
Is it userId or userID? parseHTTPResponse or parseHttpResponse?
The rule that ends the argument is to treat an acronym as an ordinary word: userId, parseHttpResponse, XmlHttpRequest. Several major style guides say exactly this, and the reason is mechanical rather than aesthetic. parseHTTPResponse has no boundary between the acronym and what follows, so it cannot be split back into words by any tool, and two adjacent acronyms are unreadable. Go is the notable exception, where the standard library keeps URL and ID capitalised — follow the language you are in.
Pick one and apply it everywhere. The cost of the wrong choice is small. The cost of both choices is a codebase where you cannot guess a name without looking it up.
Converting without breaking things
When you have a list of names to convert — column names into properties, a set of constants, an enum — our Case Converter takes the whole block at once and gives you all eight forms, including the programming cases that strip spaces and punctuation between words. The text is converted in your browser, so an internal schema is not being pasted onto somebody's server.
Three cautions:
- Never run a whole source file through a case conversion. It cannot tell an identifier from a string literal, a URL, or a comment. Convert lists of names, not code.
- Blind find-and-replace on a name catches substrings. Renaming
userwill hitusernameanduserGroup. Use your editor's rename-symbol command, which understands scope, or anchor the search with word boundaries. - Check the round trip. Conversion between cases loses information when a name contains digits or single-letter words —
v2Api,xAxis. Convert, then read the result rather than trusting it.
If you are renaming across a live system, the safe sequence is to add the new name, support both for a release, then remove the old one. A rename that is instant in the editor is not instant in a database with existing rows.
Common questions
What case should JSON keys use?
There is no standard, which is why this comes up. The common practice is to follow the language that produces the API, so a Python service ships snake_case and a Node service ships camelCase. Consistency within one API matters far more than which one you pick — a payload mixing both is the only genuinely wrong answer.
Does case matter in a URL?
The domain is case-insensitive, but the path usually is not on Linux-based servers, so /About and /about can be two different pages. Keep paths lowercase and hyphenated, and redirect the variants rather than serving both.
Should file names be kebab-case or snake_case?
Follow the ecosystem: kebab-case for web assets and packages, snake_case in Python projects where the file name is also the module name, and PascalCase for files that hold a single class or component in frameworks that expect it. Avoid spaces and uppercase in any file name that will appear in a URL.
More guides
- How to Tell if a Website Is Really Uploading Your Files
- How Much House Can You Actually Afford?
- How to Make a Passport Photo From a Phone Picture
- How to Send Only the Pages You Need From a PDF
- How to Merge Scanned Pages Without the Order Going Wrong
- What You're Actually Pasting Into an Online JSON Formatter
- Why Two Names That Look Identical Don't Match
- Five Regex Patterns That Look Right and Quietly Aren't
- Asking AI for the First Time: What to Ask, and What Not to Paste