camelCase vs snake_case: The Great Naming Debate
Two Styles, One Problem
Every developer eventually faces this question: should you write firstName or first_name? The answer depends on your language, your team, and — surprisingly — on cognitive science. Let's break down the real differences.
Origins of Each Style
camelCase emerged from early programming languages where spaces were invalid in identifiers. Lisp hackers in the 1960s used hyphens (first-name), but when languages like C and Java reserved the hyphen for subtraction, developers shifted to capitalizing internal words. Smalltalk popularized the style, and Java cemented it as the default for millions of developers.
snake_case has older roots in C and the Unix tradition. Underscores were valid identifier characters and visually separated words without changing letter case. Python adopted snake_case wholesale in the 1990s, and Ruby followed. The style aligns naturally with how people write in plain English when spaces are not available (e.g., first_name).
What Research Says About Readability
In 2010, a controlled eye-tracking study by Binkley et al. found that snake_case identifiers were read 20% faster than camelCase identifiers on average. The underscores act as visual word boundaries, making it easier for the brain to split the identifier into its component words.
However, the study also found that familiarity reduces the gap. Developers who work primarily in camelCase languages perform almost as well with camelCase as with snake_case. The readability advantage shrinks with daily exposure.
A later replication by Schankin et al. (2017) confirmed the direction but found a smaller effect size (around 10%). The consensus: snake_case has a measurable edge for new readers, but the difference is small for experienced practitioners in either style.
Language Ecosystem Choices
The programming languages you use heavily influence which style feels natural. Here is how the major ecosystems line up.
| Ecosystem | Primary Style | Reason |
|---|---|---|
| JavaScript / TypeScript | camelCase | Language spec, DOM APIs, JSON |
| Java / Kotlin | camelCase | Official style guides |
| C# | camelCase / PascalCase | Microsoft conventions |
| Python | snake_case | PEP 8 style guide |
| Ruby | snake_case | Community convention |
| Rust | snake_case | Compiler-enforced for functions |
| Go | camelCase | Export visibility tied to case |
| C / C++ | Mixed | No single convention dominates |
The JSON-to-Python Problem
One of the most practical pain points is the mismatch between JSON APIs (camelCase) and Python backends (snake_case). Every Python developer who consumes a JSON API has faced this:
{
"firstName": "Alice",
"lastName": "Smith",
"isActive": true
}
# Manual conversion — tedious and error-prone
first_name = data["firstName"]
last_name = data["lastName"]
is_active = data["isActive"]
Popular solutions include:
- pydantic —
alias_generatorconfig option that maps camelCase to snake_case automatically - marshmallow —
data_keyparameter for field-level mapping - Custom deserialization functions — Convert keys at the API boundary
The key principle: convert at the boundary, use native conventions inside. Never let camelCase variables leak deep into a snake_case codebase.
Database Column Naming
Most SQL databases default to lowercase identifiers, and underscores handle word separation naturally. This makes snake_case the overwhelming convention for database schemas:
CREATE TABLE users (
first_name VARCHAR(100),
last_name VARCHAR(100),
created_at TIMESTAMP
);
Object-relational mappers (ORMs) like SQLAlchemy, Django ORM, and ActiveRecord all default to snake_case column names. If your application uses camelCase internally, the ORM typically handles translation at the data layer boundary.
Handling Mixed Codebases
Large systems often combine languages. A typical web stack might involve JavaScript (camelCase) on the frontend, Python (snake_case) on the backend, and SQL (snake_case) in the database. Here is how to keep things manageable:
- Follow each language's convention inside its own layer. Do not write Python in camelCase to match the frontend.
- Convert at the boundaries. API serializers and ORM mappings handle the translation.
- Document the mapping convention. Make it clear where conversion happens so new developers do not duplicate or skip it.
- Use automated conversion tools. Libraries like
humps(Python) orlodash.camelCase(JS) handle bulk conversions reliably.
Practical Comparison
| Aspect | camelCase | snake_case |
|---|---|---|
| Visual density | Higher (no separator characters) | Lower (underscores add spacing) |
| Typing speed | Faster (no underscore key) | Slightly slower |
| Readability for new readers | Lower | Higher (research-backed) |
| Readability for experienced users | Comparable | Comparable |
| Language support | JS, Java, C#, Go | Python, Ruby, Rust, SQL |
| All-caps handling | Ambiguous (parseXML vs parseXml) | Clear (parse_xml) |
The all-caps ambiguity in camelCase is worth noting. How do you capitalized an acronym? parseXML? parseXml? parseXmL? Different teams answer differently. snake_case avoids the question entirely: parse_xml.
Key Takeaways
- snake_case has a measurable readability edge for unfamiliar code, but familiarity closes the gap.
- Your language ecosystem determines the "right" answer more than personal preference.
- The JSON-to-Python mismatch is real — automate conversion at the API boundary.
- Database schemas overwhelmingly use snake_case, regardless of application language.
- In mixed-language stacks, follow each language's convention and convert at boundaries.
- All-caps abbreviations are ambiguous in camelCase; snake_case sidesteps the issue entirely.
Try It Yourself
Need to switch between naming styles? Try this tool:
- Case Converter — Instantly convert between camelCase, snake_case, PascalCase, and kebab-case
Related Guides
- Naming Conventions Guide — Full overview of camelCase, PascalCase, snake_case, and kebab-case across languages
- Code Readability Tips — Practical techniques for writing code others can understand