camelCase, snake_case or kebab-case?

Naming Conventions by Language

· Open the Case Converter

Use whatever the language or format you are writing in expects, because the convention is part of how readers and tools parse your code. In practice: camelCase for variables and functions in JavaScript, TypeScript, Java, Kotlin, Swift and C# locals; snake_case for variables and functions in Python, Ruby, Rust and SQL; PascalCase for types and classes almost everywhere; UPPER_SNAKE_CASE for constants and environment variables; kebab-case for URLs, CSS classes, HTML attributes, command-line flags and most file names on the web. Where two conventions meet, such as a Python service returning JSON to a JavaScript client, pick one for the boundary, document it, and convert at the edge.

The five cases

Name Example Word boundary Typical home
camelCase retryCount Uppercase letter JS/TS/Java/Swift/Kotlin variables and methods
PascalCase (UpperCamelCase) RetryCount Uppercase letter Types, classes, components in most languages
snake_case retry_count Underscore Python, Ruby, Rust, SQL, C standard library
UPPER_SNAKE_CASE (CONSTANT_CASE) RETRY_COUNT Underscore Constants, environment variables, C macros
kebab-case retry-count Hyphen URLs, CSS, HTML attributes, CLI flags, file names

kebab-case cannot be used for identifiers in most programming languages because retry-count parses as retry minus count. That single fact explains most of the table: kebab-case lives wherever names are strings or markup rather than code.

By language

Language Variables, functions Types, classes Constants Modules, packages, files Enforced by
JavaScript / TypeScript camelCase PascalCase (also React components) UPPER_SNAKE for module-level constants kebab-case.ts common; component files often PascalCase.tsx Linters only
Python snake_case PascalCase UPPER_SNAKE snake_case.py; hyphens make a module unimportable PEP 8, linters
Java / Kotlin camelCase PascalCase UPPER_SNAKE (static final) lowercase reverse-domain packages; file name must equal the public class Compiler (file name), style guides
C# locals and parameters camelCase; methods, properties PascalCase PascalCase; interfaces IPascalCase PascalCase Namespaces PascalCase .NET design guidelines, analyzers
Go camelCase if unexported, PascalCase if exported same rule same rule (no UPPER_SNAKE) package names short, lowercase, no underscores; files snake_case.go The compiler: case controls visibility
Rust snake_case PascalCase (types, traits, enum variants) UPPER_SNAKE (const, static) snake_case modules Compiler warnings
Ruby snake_case PascalCase UPPER_SNAKE (any capitalised name is a constant) snake_case.rb Interpreter (constants), RuboCop
PHP (PSR-1) methods camelCase PascalCase UPPER_SNAKE File per class, PascalCase.php PSR standards
Swift camelCase PascalCase camelCase (no special constant case) PascalCase.swift API design guidelines
SQL snake_case columns and tables n/a n/a n/a Case folding (see below)

Three of those entries have consequences beyond style:

  • Go uses the case of the first letter as its visibility modifier. func parseConfig is private to its package; func ParseConfig is exported. Renaming for style changes the API.
  • Ruby treats any identifier starting with a capital letter as a constant, and warns when you reassign it.
  • Go file names carry meaning in their suffixes: _test.go marks test files, and _linux.go or _amd64.go restricts a file to a platform. A file named server_linux.go for style reasons will silently disappear from macOS builds.

Outside programming languages

Context Convention Why
URLs and slugs kebab-case Search engines treat hyphens as word separators and underscores as joiners; hyphens are also unambiguous when underlined as a link
CSS classes, custom properties kebab-case (--accent-color) CSS property names are kebab-case; BEM adds block__element--modifier
HTML data- attributes kebab-case The DOM maps data-user-id to element.dataset.userId automatically
CLI flags --kebab-case POSIX and GNU convention (--dry-run)
Environment variables UPPER_SNAKE POSIX portable names are uppercase letters, digits and underscore
SQL identifiers snake_case, lowercase Unquoted names fold to lowercase in PostgreSQL and uppercase in Oracle and the standard; lowercase snake_case survives both
JSON APIs camelCase or snake_case No standard; camelCase matches JavaScript consumers, snake_case matches Python and Ruby producers. Consistency matters more than the choice
YAML configuration Follows the tool Kubernetes uses camelCase keys, Compose files snake_case, many CI systems kebab-case
Git branches, Docker images kebab-case, lowercase Image repository names must be lowercase

The SQL row is worth expanding. A column created as "createdAt" in PostgreSQL must be quoted with that exact case in every query; unquoted createdAt folds to createdat and fails. That is why ORMs map createdAt in code to created_at in the database, and why the SQL style guide recommends lowercase snake_case.

Acronyms: the part nobody agrees on

The hardest naming question is not which case to use but how to treat initialisms like ID, URL, HTTP and XML inside a camelCase or PascalCase name. The official style guides disagree:

Concept Java (Google style) C# (.NET guidelines) Go Rust Swift Python (PEP 8)
user ID variable userId userId userID user_id userID user_id
HTTP server type HttpServer HttpServer HTTPServer HttpServer HTTPServer HTTPServer
XML HTTP request type XmlHttpRequest XmlHttpRequest XMLHTTPRequest XmlHttpRequest XMLHTTPRequest XMLHTTPRequest
IO stream type IoStream IOStream (two-letter acronyms stay upper) IOStream IoStream IOStream IOStream
parse URL function parseUrl ParseUrl parseURL parse_url parseURL parse_url

Two philosophies are in play. Treating an acronym as a word (XmlHttpRequest) keeps word boundaries visible and makes mechanical conversion reliable. Keeping acronyms uppercase (XMLHTTPRequest) preserves how the term is normally written, at the cost of ambiguity: XMLHTTPRequest could be split as XMLHTTP Request. Even standard libraries are inconsistent; the JDK has both HttpURLConnection and URLEncoder, and the browser's own XMLHttpRequest mixes both styles in one name.

For new code, the word-style rule is easier to live with: every word, including acronyms, gets exactly one leading capital. It round-trips cleanly between cases, which matters as soon as a name travels from a database column to a JSON field to a class property.

Converting between cases

Converting user id, HTTPResponseCode or max_retry_count to another case means first splitting the name into words, then joining them with the target convention. The Case Converter does both, one name per line:

Mixed names to snake_caseOpen in Case Converter
user id
HTTPResponseCode
XMLHttpRequest
max_retry_count
created-at

With Case set to snake_case, the result is:

Text
user_id
http_response_code
xml_http_request
max_retry_count
created_at

The splitter recognises a run of capitals followed by a capitalised word (HTTPResponse becomes http and response), which handles the common cases. Some names defeat any mechanical splitter because the information needed is not in the string: userIDs comes out as user_i_ds, IPv6Address as i_pv6_address, and OAuth2Token as o_auth2_token. A converter cannot know that IDs is a plural acronym or that OAuth is one word. Convert in bulk, then review the names containing acronyms, digits or mixed-case brand names by hand; this is another argument for the acronym-as-word style, whose names convert without surprises.

Beyond case: words that carry meaning

Case is only half of a name. A few word-level conventions are close to universal and worth adopting alongside whichever case you use:

  • Booleans read as questions: isActive, has_children, shouldRetry. A bare active could be a flag, a timestamp or a list.
  • Units in the name: timeout_ms, size_bytes, created_at_s. This prevents the most common numeric bugs, such as passing seconds where milliseconds are expected, described in the Unix timestamps guide.
  • Plurals for collections: users for a list, user for one item, user_ids for a list of identifiers.
  • No type prefixes: Hungarian notation (strName, iCount) predates type-aware editors and goes stale when the type changes.
  • Suffixes by convention: ...Error or ...Exception for error types, ...Test or test_... for tests, so tools and readers can find them.

Practical rules

  1. Follow the host language's convention inside its code, even when you prefer another. Readers of Python expect snake_case; fighting it costs more than it saves.
  2. At boundaries (API payloads, database columns, configuration keys), choose one convention per boundary, document it, and convert in one place: a serializer setting, an ORM naming strategy, or a mapping layer.
  3. Treat acronyms as words in camelCase and PascalCase unless your language's guide says otherwise (Go, Swift, Python and C# for two-letter acronyms do).
  4. Never rely on case alone to distinguish two names in systems that fold case: SQL, Windows and macOS file systems, email addresses, DNS names.
  5. Use UPPER_SNAKE_CASE only for true constants and environment variables, so that it keeps meaning "this does not change at runtime".

Tools used in this guide