The choice between camelCase and snake_case feels arbitrary if you don't know the history. It isn't. The split reflects real differences in language design, terminal display, and the cultural preferences of the developer communities that built each language.

Most languages don't actually let you choose — they enforce a convention through documentation, linters, and peer review. Pythonists write user_name. JavaScript developers write userName. C# developers write UserName. Picking the wrong one for the language flags you as someone who doesn't know the community standards.

Here's where each convention comes from, where it works, and how to make the right choice.

What camelCase actually is

camelCase is a naming convention where the first word starts lowercase and every subsequent word starts with a capital letter, with no separators between them. userName. parseHttpRequest. getElementById.

The name comes from the visual rhythm of the capitals — they look like the humps on a camel's back.

It's the default convention in:

  • JavaScript (variables, functions, methods)
  • Java (variables, methods — but PascalCase for class names)
  • C# (local variables, parameters — but PascalCase for class/method names)
  • TypeScript (variables, functions)
  • Swift (variables, functions, parameters)
  • Kotlin (variables, functions)
  • Objective-C (variables, methods)
  • Dart (variables, functions)

What snake_case actually is

snake_case writes all words in lowercase with underscores between them. user_name. parse_http_request. get_element_by_id.

It's the default in:

  • Python (variables, functions, modules)
  • Ruby (variables, methods)
  • Rust (variables, functions, modules)
  • SQL (column names, table names — though varies by database)
  • YAML / TOML (configuration keys)
  • Bash / Shell scripts (variables)
  • Crystal (variables, methods)
  • Elixir (variables, functions)

The historical origin

camelCase predates snake_case in widespread use. The convention dates to Smalltalk-72 (designed by Alan Kay at Xerox PARC in the early 1970s), which encouraged compact identifiers with capitalized word breaks. The pattern spread to languages that descended from Smalltalk and from C — including the Java and C# families.

snake_case has older roots in C library naming (think strcpy, memcpy — though those are usually just compressed). Python adopted snake_case explicitly when Guido van Rossum wrote PEP 8 in 2001. PEP 8 codified snake_case for variables and functions because it argued that lowercase identifiers with explicit separators are more readable than camelCase, especially for non-native English speakers who don't intuit word boundaries from capital letters.

Ruby followed Python. Rust, designed in part by people who valued explicitness, also followed.

The readability argument

There's a long-running argument about which convention is more readable. Both sides have evidence:

Pro camelCase: more compact, fewer characters, more density per line. Word boundaries are visible (humps) without requiring a separator character.

Pro snake_case: explicit separators make word boundaries unambiguous. Easier to read for non-native English speakers. Easier to highlight (you can double-click user_name in a terminal and select the whole identifier; double-clicking userName usually selects only one of the two words).

Empirical studies (notably Sharif and Maletic, 2010, which used eye-tracking on programmers reading both styles) suggest that snake_case is read slightly faster but identified slightly less accurately than camelCase. The differences are small.

In practice, both are readable to anyone fluent in the convention. The choice is dictated by language conventions, not by individual preference.

When to use each

Use camelCase if you're writing in: JavaScript, TypeScript, Java, C# (variables/parameters), Swift, Kotlin, Objective-C, Dart, Groovy.

Use snake_case if you're writing in: Python, Ruby, Rust, Elixir, Crystal. Also use snake_case for SQL column names, YAML keys, environment variable names (in CONSTANT_CASE — see below), and most configuration files.

Use PascalCase (capitalize first letter too — UserName) for class names in almost every OO language: Java, C#, Python, Ruby, Swift, Kotlin, etc.

Use CONSTANT_CASE (also called SCREAMING_SNAKE_CASE — USER_NAME) for constants in almost every language: C, Java, JavaScript, Python (for module-level constants), and especially for environment variables.

The edge cases that trip people up

Acronyms in camelCase

Should HTMLParser be camelCased as HTMLParser or htmlParser?

The Java convention (and most modern style guides) treats acronyms as words: only the first letter is capitalized. So HTMLParser becomes htmlParser in camelCase, HtmlParser in PascalCase. XMLHttpRequest becomes xmlHttpRequest or XmlHttpRequest.

Older conventions kept acronyms in all caps: HTMLParser stays as-is in some Java code, JavaScript's own XMLHttpRequest class breaks the modern convention. New code should follow the "acronym as word" rule.

Our case converter handles this tokenization correctly — HTMLParserhtmlParser in camel mode, html_parser in snake mode.

Numbers in identifiers

Numbers usually don't get separated from adjacent words: parseUtf8, parse_utf8. Numbers are treated as suffixes to the preceding word, not as separate tokens.

Single-letter names

Single-letter names (i, j, x) are usually preserved as-is in both conventions. They're typically used for loop indices and short-scope variables.

Boolean prefixes

Boolean variables conventionally start with is, has, or can: isLoggedIn (camelCase) or is_logged_in (snake_case). This is a stylistic convention, not a hard rule.

Mixing conventions in one codebase

Most codebases mix conventions naturally because different file formats use different styles. A Python web app might have:

  • Python code in snake_case: def get_user_profile(user_id):
  • SQL column names in snake_case: SELECT user_id, created_at FROM users
  • JSON response keys in camelCase: {"userId": 123, "createdAt": "..."} (matching the JavaScript frontend)
  • HTML attributes in kebab-case: <div data-user-id="123">
  • CSS class names in kebab-case: .user-profile
  • Environment variables in CONSTANT_CASE: DATABASE_URL

This isn't inconsistency — it's matching each format to its language's convention. The frontend devs see camelCase JSON because their language is JavaScript. The backend devs see snake_case Python because their language is Python. The conversion happens at the API boundary.

Tooling for case conversion

If you're moving data between systems with different conventions, our case converter has a smart tokenizer that handles all the edge cases — ALLCAPS runs, numeric suffixes, single-letter words, mixed input. Pasting a list of camelCase identifiers and converting them to snake_case (or vice versa) takes one click.

The bulk converter handles entire files of identifiers if you're doing a one-time migration — useful for renaming a Python module's variables to match a new naming standard, or converting a SQL schema to a different convention.

Don't fight your language's convention

The single biggest mistake new developers make is writing camelCase code in Python because they came from a JavaScript background, or snake_case in JavaScript because they came from Python. This works syntactically but flags you as an outsider in code reviews.

Languages have communities. Communities have conventions. Following the convention isn't conformity for its own sake — it makes your code easier for the next person to read. Pay the small cost of switching conventions when you switch languages.