Naming Conventions in Programming: camelCase, snake_case, kebab-case and More

Every programmer encounters the question: should this be myVariable,my_variable, or my-variable? The answer depends on the language, the context, and the layer of the stack. This guide explains when each convention is appropriate and why.

The Six Main Naming Conventions

All naming conventions are strategies for combining multiple words into a single identifier. Programming languages require identifiers without spaces, so conventions emerged to make multi-word names readable.

ConventionExampleAlso known as
camelCasegetUserByIdLower camel case, dromedary case
PascalCaseUserProfileUpper camel case, StudlyCase
snake_caseuser_profileUnderscore case, pothole case
kebab-caseuser-profileHyphen case, lisp-case, spinal-case
SCREAMING_SNAKEMAX_RETRY_COUNTAll caps, constant case, macro case
dot.caseapp.server.portDot notation

Convention by Language

JavaScript and TypeScript

// Variables and functions → camelCase
const userCount = 42;
function getUserById(id: string) {}

// Classes and interfaces → PascalCase
class UserService {}
interface UserProfile {}
type ApiResponse = {}

// Constants → SCREAMING_SNAKE_CASE
const MAX_RETRIES = 3;
const API_BASE_URL = "https://api.example.com";

// React components → PascalCase (required)
function UserCard({ user }: Props) {}

// CSS class names (via Tailwind/CSS Modules) → kebab-case
// .user-card, .nav-link, .primary-button

Python

# Variables and functions → snake_case
user_count = 42
def get_user_by_id(user_id: str): ...

# Classes → PascalCase
class UserService:
    pass

# Constants → SCREAMING_SNAKE_CASE
MAX_RETRIES = 3
DATABASE_URL = "postgresql://..."

# Private/internal → leading underscore
def _internal_helper(): ...
self._private_attr = True

# "Name mangling" (truly private) → double underscore
self.__really_private = True

Go

// Exported (public) identifiers → PascalCase
type UserProfile struct {}
func GetUserByID(id string) {}

// Unexported (package-private) → camelCase
type userCache struct {}
func getUserFromCache(id string) {}

// Acronyms stay fully capitalized (Go convention)
// ID not Id, URL not Url, HTTP not Http
func ParseHTTPResponse(r *http.Response) {}
type UserID string

Java and Kotlin

// Variables and methods → camelCase
int userCount = 42;
public User getUserById(String id) {}

// Classes and interfaces → PascalCase
public class UserService {}
public interface UserRepository {}

// Constants → SCREAMING_SNAKE_CASE
public static final int MAX_RETRIES = 3;
public static final String API_URL = "...";

// Packages → lowercase (no separators)
package com.example.userservice;

CSS and HTML

/* CSS class names → kebab-case (universal convention) */
.user-card {}
.nav-link:hover {}
.primary-button--disabled {}

/* CSS custom properties (variables) → kebab-case */
:root {
  --color-primary: #6366f1;
  --font-size-base: 1rem;
}

<!-- HTML attributes → kebab-case -->
<div data-user-id="123" aria-label="User profile"></div>
<my-custom-element></my-custom-element>

SQL and Databases

-- PostgreSQL → snake_case (idiomatic)
CREATE TABLE user_profiles (
  user_id     UUID PRIMARY KEY,
  first_name  TEXT NOT NULL,
  created_at  TIMESTAMPTZ DEFAULT NOW()
);

-- Stored procedures → snake_case
CREATE FUNCTION get_user_by_email(p_email TEXT) ...

Convention by Context

Beyond language conventions, context determines naming style:

  • Environment variablesSCREAMING_SNAKE_CASE universally: DATABASE_URL, JWT_SECRET
  • URL slugs and routeskebab-case: /user-profile, /api/v1/user-tokens
  • JSON API keyscamelCase (JavaScript convention) or snake_case (Python/Ruby APIs): pick one and be consistent
  • File names → depends on OS and language: kebab-case for web assets, PascalCase for React components, snake_case for Python modules
  • Config file keyssnake_case in YAML, camelCase in JSON, kebab-case in TOML
  • Package/module nameskebab-case in npm (my-package), snake_case in Python (my_module)

Why Consistency Beats Correctness

In a greenfield project, pick one convention per context and enforce it with a linter (ESLint, Pylint, golangci-lint). In an existing codebase, follow whatever is already there — a consistent snake_case codebase is better than a mixed camelCase/snake_case one, even if camelCase would technically be "more idiomatic."

Use the Text Case Converter to quickly transform identifiers between conventions — useful when translating database column names to API response keys, or when copying code between languages.

Frequently Asked Questions

Does naming convention affect performance?

No, naming conventions have zero effect on runtime performance. The compiler or interpreter treats myVariable and my_variable identically from an execution standpoint. Conventions exist entirely for human readability, team consistency, and tool interoperability (linters, code generators, ORMs that map column names to property names). Follow the convention of your language and codebase.

What happens when different layers of a stack use different conventions?

This is common and expected — a PostgreSQL database uses snake_case columns, a JavaScript frontend uses camelCase properties, and a REST API returns JSON. The mapping layer (ORM, JSON serializer) handles the conversion automatically. In JavaScript, libraries like humps or axios-case-converter can auto-transform snake_case API responses to camelCase objects. In Python, Pydantic's alias_generator handles this. Agreeing on a convention per layer and automating the transformation is better than forcing one convention everywhere.

What is Hungarian notation and should I use it?

Hungarian notation prefixes variable names with type information: strName, intCount, bIsValid. It was popular in 1980s-90s C programming when IDEs had no type inference. Modern languages have static types, type inference, and IDE tooltips that make the prefix redundant and verbose. Most modern style guides (Google, Microsoft, Airbnb) explicitly discourage it. Avoid it in new code — let the type system and meaningful names carry the type information.