Utilo

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 use camelCase for const variables.
  • File names: often kebab-case (user-profile.tsx) or PascalCase for 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 like HTTPSURLConnection and converts cleanly between cases — parseHttpResponse becomes parse_http_response automatically.
  • 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:

  1. Use one convention on the wire. Decide that JSON uses camelCase (the most common choice for public APIs, matching JavaScript) or snake_case (common in Python and Ruby ecosystems, and used by APIs such as Stripe and GitHub). Document it and apply it everywhere.
  2. 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.
  3. 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, info and item say nothing. invoiceLines says a lot.
  • Use verbs for functions and nouns for values. calculateTotal() returns total.
  • Name booleans as questions. isActive, hasAccess, shouldRetry.
  • Include units. timeoutMs, maxSizeBytes, durationSeconds prevent a whole class of bugs.
  • Avoid abbreviations unless they are universal (id, url, html). usrCnt saves four characters and costs every reader a moment.
  • Match the domain language. If the business says "subscription", do not call it plan in 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.

Related guides