camelCase, snake_case or kebab-case: Which Goes Where
Naming conventions are not preferences. Each language and format has one the tooling expects, and going against it costs more than it looks.
· 3 min read
Programmers cannot use spaces in identifiers, so every language invented a way to glue words together. The result is half a dozen conventions that all encode the same information and are not interchangeable, because each ecosystem standardised on one and built tooling that assumes it.
The conventions, and who uses them
- camelCase — first word lowercase, later words capitalised. Variables and functions in JavaScript, Java, C# methods, Swift and Kotlin.
- PascalCase — every word capitalised, including the first. Classes, types and components almost everywhere, plus C# method names.
- snake_case — all lowercase, underscores between words. Python, Ruby, Rust, C, and the overwhelming majority of SQL schemas.
- SCREAMING_SNAKE_CASE — uppercase with underscores. Constants and environment variables in nearly every language.
- kebab-case — lowercase with hyphens. CSS classes, URL paths, HTML attributes, npm package names, most command-line flags.
Why the boundaries are hard
kebab-case is impossible in most languages because the hyphen is the subtraction operator, so a name like user-id parses as a subtraction of two variables. That single fact explains most of the split: places where hyphens are legal use them, and places where they are not fall back to underscores or capitalisation.
Conversely, snake_case is a poor fit for URLs. Search engines have long treated a hyphen as a word separator and an underscore as a word joiner, which means my_page reads as one token and my-page reads as two. For anything that has to be found, the hyphen is not a style choice.
A convention is worth following not because it is better, but because the tooling, the linters and the next reader all assume it.
The boundary problem nobody agrees on
Converting between conventions is easy until an acronym appears. Is the camelCase form of "HTTP server" httpServer or hTTPServer? Is the class HTTPServer or HttpServer? Both are defensible, both are in wide use, and the two convert back differently — HTTPServer to snake_case gives either http_server or h_t_t_p_server depending on how the splitter handles consecutive capitals.
HTTPServer -> http_server (treat runs of capitals as one word)
HTTPServer -> h_t_t_p_server (split on every capital)
parseHTTPResponse -> parse_http_response correct
parseHTTPResponse -> parse_h_t_t_p_response the naive resultMost style guides now recommend treating acronyms as ordinary words — HttpServer, parseHttpResponse — precisely because it makes conversion unambiguous in both directions. Google and Microsoft both moved this way for exactly that reason. If you are choosing today, choose that.
Digits, and other edge cases
Numbers create the same ambiguity as acronyms. Should base64Encoder become base_64_encoder or base64_encoder? Should utf8 stay together? There is no universal answer, so the practical rule is to keep a digit attached to the word it belongs to and to check the result rather than trust the conversion. A converter cannot know that "s3" is a product name and "v2" is a version.
Where it costs real money
The expensive case is a boundary between systems. A JavaScript front end holds camelCase, a Python or SQL back end holds snake_case, and the JSON between them has to pick one. Choosing per-field, or converting in some code paths and not others, produces bugs that are invisible in review and obvious in production: a field silently reads as undefined because it was firstName on one side and first_name on the other.
Pick one convention for the wire format, write it down, and convert at exactly one layer on each side. Which one you pick matters far less than that the boundary is a single place rather than scattered through the code.
The filesystem trap
One more reason lowercase wins for filenames: macOS and Windows are case-insensitive by default, and Linux is not. A component imported as Button that lives in a file called button works on a developer laptop and fails in a Linux build container. Keeping filenames in kebab-case removes the entire class of problem.
Frequently asked questions
- Which case should I use for JSON API fields?
- Whichever one you can apply consistently across the whole API. camelCase is the most common in public APIs because most consumers are JavaScript, but snake_case is equally valid. The cost is in mixing them, not in the choice.
- Why do search engines prefer hyphens over underscores in URLs?
- A hyphen has long been treated as a word separator and an underscore as a joiner, so my-page is read as two words and my_page as one. That affects which queries the URL can help you match.
- Is PascalCase the same as camelCase?
- No. Both capitalise interior words, but PascalCase also capitalises the first one. PascalCase is conventionally reserved for classes, types and components, and camelCase for variables and functions.
Related reading
- 3 min read
encodeURI or encodeURIComponent? One Rule That Works
The two differ by eleven characters, and picking wrong either breaks the URL or corrupts the value. Here is the rule, and the plus-sign trap.
- 3 min read
Favicon Sizes You Actually Need
Generators offer dozens of sizes and almost nobody needs them all. Which files earn their place, which link tags matter, and why 16px decides it.
- 3 min read
How Much Can You Compress an Image Before It Shows?
The quality number is not a percentage of anything. What the artefacts look like, where they appear first, and how to find your own limit.
- 3 min read
PNG, JPEG or WebP: Which One, and Why
Three formats, one decision, and it hinges on what the image contains rather than on which format is newest. A rule and its exceptions.