# OpenMetadata Coding Standards: Complete Guide to Java, TypeScript, and Python Guidelines

> Master OpenMetadata coding standards for Java, TypeScript, and Python. Ensure production-ready, maintainable code with our comprehensive guide and CI enforced guidelines.

- Repository: [OpenMetadata/OpenMetadata](https://github.com/open-metadata/OpenMetadata)
- Tags: best-practices
- Published: 2026-04-23

---

**OpenMetadata enforces strict, cross-language coding standards documented in [`CLAUDE.md`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md) and enforced automatically via CI pipelines to ensure production-ready, maintainable code.**

The [OpenMetadata](https://github.com/open-metadata/OpenMetadata) project maintains a unified codebase spanning Java backend services, TypeScript/React front-end applications, and Python ingestion connectors. This guide breaks down the project's coding standards as defined in [`CLAUDE.md`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md) and [`DEVELOPER.md`](https://github.com/open-metadata/OpenMetadata/blob/main/DEVELOPER.md), with practical examples from the source code.

---

## General Coding Principles

All contributors must follow these foundational rules across every language:

- **No unnecessary comments** — write self-documenting code with clear naming
- **Every change must pass CI lint and format checks** before merge
- **Follow language-specific standards** detailed in the sections below

These rules appear in [`CLAUDE.md – Comments Policy`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md#comments-policy) and are enforced in `.github/workflows/**` pipelines.

---

## Java Coding Standards

The OpenMetadata backend in `openmetadata-service/src/main/java/**` follows strict Java 21 conventions defined in [`CLAUDE.md – Java Code Requirements`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md#java-code-requirements).

### Formatting and CI Enforcement

Run `mvn spotless:apply` after every Java change. The CI pipeline fails if code is unformatted.

### Method Structure Rules

| Metric | Limit | Rationale |
|--------|-------|-----------|
| Method length | ≤ 15 lines | Single responsibility |
| Nesting levels | ≤ 3 | Readable control flow |
| Cyclomatic complexity | ≤ 10 | Testable paths |
| Parameters | ≤ 5 | Use parameter objects |

### Import and Modifiers

- **No wildcard imports** — import only required classes
- Use `final` for immutable local variables
- Make defensive copies for collections passed to constructors

### Modern Java 21 Features

Prefer pattern matching, switch expressions, `List.of()`, and correct `Optional` usage. Avoid magic strings — use constants or enums.

### Java Example: Clean Method Structure

```java
// ✅ Good: short, single-purpose, early-return style
public void deleteEntity(UUID id) {
    Entity entity = getEntity(id);
    if (entity == null) {
        throw new EntityNotFoundException(id);
    }
    if (!entity.isDeletable()) {
        throw new IllegalArgumentException("Entity cannot be deleted");
    }
    repository.delete(entity);
}

```

This method from `openmetadata-service` demonstrates the 15-line limit, early returns, and clear naming that [`CLAUDE.md`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md) requires.

---

## TypeScript and Front-End Coding Standards

The React application in `openmetadata-ui/src/main/resources/ui/**` follows strict TypeScript rules documented in [`CLAUDE.md – TypeScript/Frontend Code Requirements`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md#typescriptfrontend-code-requirements).

### Type Safety

- **Never use `any`** — use proper types or `unknown` with type guards
- The ESLint `no-unsafe-any` rule catches violations

### Import Organization

Follow strict import ordering:
1. External libraries
2. Internal absolute imports
3. Relative imports
4. Assets

Run `yarn organize-imports:cli` before committing.

### ESLint Rules

| Rule | Requirement |
|------|-------------|
| No `console.log` in production | Remove or use proper logging |
| Strict equality | `===` over `==` |
| Line length | Maximum 200 characters |
| JSX | Self-closing tags, alphabetic props |

### Formatting

Run `yarn prettier` before every commit.

### Internationalization

All UI strings must use `useTranslation` with keys from locale JSON files. Run `yarn i18n` to sync keys across all locales. Keys use **kebab-case**.

### TypeScript Example: Proper Typing and i18n

```tsx
import type { Table } from 'generated/api/v1/table';
import type { RJSFSchema } from '@rjsf/utils';

const TableCard: React.FC<{ table: Table }> = ({ table }) => {
  const { t } = useTranslation();
  return (
    <Card title={t('label.table')}>
      <pre>{JSON.stringify(table, null, 2)}</pre>
    </Card>
  );
};

```

This component from `openmetadata-ui` demonstrates no `any`, proper import ordering, and `useTranslation` for the `'label.table'` key.

---

## Python Ingestion Coding Standards

The ingestion framework in `ingestion/src/metadata/**` follows pytest-based standards in [`CLAUDE.md – Python Code Requirements`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md#python-code-requirements).

### Testing Framework

- Use **pytest** exclusively — no `unittest`
- Use plain `assert` statements, not `self.assertEqual()`
- Replace `setUp`/`tearDown` with pytest fixtures

### Test Design

- Mock external services only — prefer integration tests for real behavior
- Every bug fix must add a failing test first

### Connector Organization

Keep connector-specific logic in its own directory. Never place connector code in shared helper files like [`builders.py`](https://github.com/open-metadata/OpenMetadata/blob/main/builders.py).

### Formatting

Run `make lint` and `make py_format` before committing. These enforce Pylint, Black, and isort rules.

### Python Example: Proper Connector Placement and pytest

```python

# ingestion/src/metadata/ingestion/source/database/postgres/connection.py

class PostgresConnection(BaseSQLConnection):
    def get_service_connection(self) -> PostgresConnectionConfig:
        # Connector-specific logic lives here

        return self.config

def test_postgres_connection_success():
    conn = PostgresConnection(config=valid_cfg)
    assert conn.test_connection() is True

```

This follows the rule that `PostgresConnection` stays in `postgres/` rather than leaking into shared [`builders.py`](https://github.com/open-metadata/OpenMetadata/blob/main/builders.py).

---

## UI Styling Standards

The design system in `openmetadata-ui` uses Tailwind with strict conventions from [`CLAUDE.md – Styling`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md#styling).

### Component Library

Use `openmetadata-ui-core-components` — **never add MUI** (Material-UI) directly.

### Tailwind Configuration

- Use `tw:` prefix for all Tailwind classes
- Reference CSS tokens from [`globals.css`](https://github.com/open-metadata/OpenMetadata/blob/main/globals.css) — no hard-coded colors or spacing

### Custom CSS

- Use BEM naming for custom CSS
- No `.less` files for new styles

### Styling Example: Tailwind with Prefix

```tsx
<div className="tw:flex tw:items-center tw:justify-between tw:bg-primary-500 tw:p-4">
  <Button>{t('label.run')}</Button>
</div>

```

Using `tw:flex` instead of `flex` ensures compatibility with the project's style linting.

---

## Testing Standards

Quality gates in `.github/workflows/**` enforce comprehensive testing rules from [`CLAUDE.md – Testing`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md#testing).

### Coverage Requirements

- **90% line coverage** on changed code
- Missing coverage blocks merge

### Asynchronous Testing

- **No `Thread.sleep()`** — use Awaitility (Java) or Playwright's web-first assertions

### Playwright E2E Rules

Avoid anti-patterns:
- No `waitForLoadState('networkidle')`
- No `page.pause()`
- No `.only` in committed tests

### Regression Testing

Every bug fix must include a failing test that proves the bug, then passes with the fix.

---

## Documentation Standards

Public APIs and UI text follow strict documentation rules in [[`CLAUDE.md`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md)](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md).

### API Documentation

All public Java and TypeScript APIs require JavaDoc or TypeScript doc comments.

### Internationalization

- All UI strings via `useTranslation` hook
- Locale keys in **kebab-case**
- Sync across all locale files with `yarn i18n`

---

## Key Configuration Files

| File | Purpose |
|------|---------|
| [[`CLAUDE.md`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md)](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md) | Central coding standards for all languages |
| [[`DEVELOPER.md`](https://github.com/open-metadata/OpenMetadata/blob/main/DEVELOPER.md)](https://github.com/open-metadata/OpenMetadata/blob/main/DEVELOPER.md) | Workflow guidance and tooling commands |
| `.github/workflows/**` | CI pipelines enforcing all standards |
| `openmetadata-service/src/main/java/**` | Java backend implementation |
| `openmetadata-ui/src/main/resources/ui/**` | React/TypeScript frontend |
| `ingestion/src/metadata/**` | Python ingestion framework |

---

## Summary

OpenMetadata coding standards create a maintainable, production-ready codebase through:

- **Automated enforcement** — CI pipelines run `mvn spotless:apply`, `yarn prettier`, `make lint`, and coverage gates
- **Strict language rules** — Java 15-line methods, TypeScript `no-any`, Python pytest patterns
- **Architectural boundaries** — connector-specific logic isolated, shared components in `openmetadata-ui-core-components`
- **Quality gates** — 90% coverage, no `Thread.sleep()`, every bug fix proven with a test

Contributors should bookmark [[`CLAUDE.md`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md)](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md) as the single source of truth and run the documented formatter commands before every commit.

---

## Frequently Asked Questions

### What is the maximum allowed method length in OpenMetadata's Java code?

Methods must be **15 lines or fewer**. This rule in [`CLAUDE.md`](https://github.com/open-metadata/OpenMetadata/blob/main/CLAUDE.md) enforces single-responsibility methods. The CI fails builds where `mvn spotless:apply` cannot automatically fix violations.

### How do I format TypeScript code before committing?

Run `yarn organize-imports:cli` followed by `yarn prettier`. These commands enforce import ordering, eliminate `any` types, and apply the 200-character line limit. The CI rejects unformatted TypeScript changes.

### Where should I place Python connector-specific logic?

Always in the connector's own directory under `ingestion/src/metadata/ingestion/source/`. Never place connector logic in shared helpers like [`builders.py`](https://github.com/open-metadata/OpenMetadata/blob/main/builders.py). This boundary prevents tight coupling and ensures clean architecture.

### What test coverage is required for code changes?

**90% line coverage** on all changed code. The CI pipeline calculates coverage and blocks merges below this threshold. Additionally, every bug fix must include a failing test that passes with the fix applied.