Naming Conventions: camelCase vs snake_case vs kebab-case vs PascalCase
A practical guide to naming conventions across JavaScript, Python, Go, SQL, CSS, URLs and environment variables, with rules for acronyms and API boundaries.
· 5 min read
Phil Karlton's famous quip says there are only two hard things in computer science: cache invalidation and naming things. Choosing good words is hard enough; then you must also decide how to join them. userId, user_id, UserId, user-id and USER_ID all describe the same concept, and each is correct somewhere. This guide explains the major conventions, where each is expected, and how to handle the awkward cases — acronyms, numbers and boundaries between systems.
The main conventions
| Name | Example | Typical use |
|---|---|---|
| camelCase | getUserById |
JavaScript/TypeScript variables and functions, Java methods, JSON fields |
| PascalCase | UserProfile |
Classes, types, React components, C# methods |
| snake_case | get_user_by_id |
Python, Ruby, Rust functions, SQL columns |
| SCREAMING_SNAKE_CASE | MAX_RETRIES |
Constants, environment variables |
| kebab-case | user-profile |
URLs, CSS classes, HTML attributes, file names, CLI flags |
| Train-Case | Content-Type |
HTTP headers |
| dot.case | app.server.port |
Configuration keys, Java packages |
A case converter can translate any name between all of these at once, which is handy when moving data between layers.
Conventions by language and context
JavaScript and TypeScript
- Variables, functions and object properties:
camelCase. - Classes, interfaces, type aliases, enums and React components:
PascalCase. React requires components to start with an uppercase letter so JSX can distinguish them from HTML elements. - True constants (configuration that never changes):
SCREAMING_SNAKE_CASE, although many codebases usecamelCaseforconstvariables. - File names: often
kebab-case(user-profile.tsx) orPascalCasefor component files. Pick one; mixed case in file names causes problems on case-insensitive file systems.
Python
PEP 8 is explicit: snake_case for functions, variables and modules, PascalCase (which PEP 8 calls CapWords) for classes, and SCREAMING_SNAKE_CASE for module-level constants. A leading underscore signals "internal": _cache.
Go
Go uses camelCase and PascalCase, and case has meaning: identifiers starting with an uppercase letter are exported from the package, lowercase are private. Go style keeps acronyms uppercase: userID, HTTPServer, parseURL.
Java and C#
Both use PascalCase for classes and camelCase for local variables. Java uses camelCase for methods; C# uses PascalCase for methods and public properties.
Rust
snake_case for functions, variables and modules; PascalCase for types and traits; SCREAMING_SNAKE_CASE for constants and statics. The compiler warns when you deviate.
SQL databases
snake_case is the safe choice for tables and columns. In PostgreSQL, unquoted identifiers are folded to lowercase, so a column created as "userId" must be quoted forever after, while user_id works everywhere. Whether table names are singular (user) or plural (users) is a matter of team preference; consistency matters more than the choice.
CSS and HTML
CSS properties are kebab-case (background-color), so class names usually follow: .card-header. Methodologies such as BEM add structure: .card__title--active. HTML attributes, including data-* attributes, are case-insensitive and conventionally kebab-case; JavaScript exposes data-user-id as element.dataset.userId.
URLs
Use lowercase kebab-case for paths: /blog/compress-image-to-100kb. Google treats hyphens as word separators but underscores as joiners, so hyphens are better for SEO. Avoid uppercase in URLs; many servers treat paths as case-sensitive, creating duplicate-content issues.
Environment variables
SCREAMING_SNAKE_CASE: DATABASE_URL, STRIPE_SECRET_KEY. Shells and container platforms expect this, and some do not allow hyphens in variable names at all.
Acronyms and initialisms
This is where teams argue most. Should it be parseHTTPResponse or parseHttpResponse? userID or userId?
- Treat acronyms as words (
parseHttpResponse,userId,XmlParser): recommended by Microsoft's .NET guidelines for acronyms longer than two letters, by Google's Java and JavaScript style guides, and by many TypeScript codebases. It avoids unreadable runs likeHTTPSURLConnectionand converts cleanly between cases —parseHttpResponsebecomesparse_http_responseautomatically. - Keep acronyms uppercase (
parseHTTPResponse,userID): standard in Go and common in older Java and Objective-C code.
Automatic converters split parseHTTPResponse as parse / HTTP / Response, which works, but HTTPSURLConnection is ambiguous. If you control the style, treating acronyms as words is more robust.
Numbers in names
Keep digits attached to the word they belong to: version2, utf8Decoder, base64_encode, h1-title. Avoid starting identifiers with digits; most languages forbid it, and CSS classes starting with digits require escaping.
Crossing boundaries: APIs and databases
Real systems mix conventions. A Python backend with snake_case serves a JavaScript front end that expects camelCase, backed by a SQL database with snake_case columns. Options:
- Use one convention on the wire. Decide that JSON uses
camelCase(the most common choice for public APIs, matching JavaScript) orsnake_case(common in Python and Ruby ecosystems, and used by APIs such as Stripe and GitHub). Document it and apply it everywhere. - Convert at the edges. Serialisation libraries can convert automatically: Pydantic's alias generators, Jackson's
PropertyNamingStrategies, or ORM column mappings. Inside each layer, code stays idiomatic. - Do not mix within one payload.
{ "userId": 1, "created_at": "..." }is the worst of both worlds.
When generating TypeScript types from JSON — covered in our JSON to TypeScript guide — keep property names exactly as they appear on the wire, and convert in a mapping layer if needed.
Choosing good words
Case style is the easy part. A few rules for the words themselves:
- Be specific.
data,infoanditemsay nothing.invoiceLinessays a lot. - Use verbs for functions and nouns for values.
calculateTotal()returnstotal. - Name booleans as questions.
isActive,hasAccess,shouldRetry. - Include units.
timeoutMs,maxSizeBytes,durationSecondsprevent a whole class of bugs. - Avoid abbreviations unless they are universal (
id,url,html).usrCntsaves four characters and costs every reader a moment. - Match the domain language. If the business says "subscription", do not call it
planin code.
Enforcing conventions
Write the conventions down and let tools enforce them: ESLint's @typescript-eslint/naming-convention rule, Pylint and Ruff for Python, golint and go vet, Rust's built-in lints, and stylelint for CSS class patterns. Automated checks end debates in code review and keep large codebases consistent.
Summary
Use camelCase for JavaScript values, PascalCase for types and components, snake_case for Python, Rust and SQL, kebab-case for URLs, CSS and file names, and SCREAMING_SNAKE_CASE for constants and environment variables. Treat acronyms as words when you can, keep units in names, choose one convention for each API, and let linters enforce the rules so humans can focus on choosing good words.