# singer-io/singer-python architecture

> Architecture diagram of the GitHub repository singer-io/singer-python, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-26). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/singer-io/singer-python
- Repository: https://github.com/singer-io/singer-python

## Overview

singer-python is a Python library for producing Singer-format data, not a standalone sync service. A tap calls its public API to emit schema, record, and state messages; it can also use catalog and metadata selection, schema-based record transformation, bookmark/state helpers, and structured metrics. The graph shows the public facade and these distinct capabilities. Some implementation excerpts are partial or absent, so links between unsampled subsystems are omitted rather than inferred.

Main entry points: [`singer/__init__.py`](https://github.com/singer-io/singer-python/blob/master/singer/__init__.py) (Library facade), [`singer/catalog.py`](https://github.com/singer-io/singer-python/blob/master/singer/catalog.py) (Catalog model), [`singer/messages.py`](https://github.com/singer-io/singer-python/blob/master/singer/messages.py) (Message writers), [`singer/logger.py`](https://github.com/singer-io/singer-python/blob/master/singer/logger.py) (Logging)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_api["Public API"]
  node_public["Library facade<br/>[__init__.py]"]
  node_utils["Tap utilities<br/>[utils.py]"]
end

subgraph group_messages["Singer Messages"]
  node_message_api["Message writers<br/>[messages.py]"]
  node_message_types["Message types<br/>[messages.py]"]
end

subgraph group_sync["Sync Support"]
  node_catalog["Catalog model<br/>[catalog.py]"]
  node_schema["Schema model<br/>[schema.py]"]
  node_metadata["Field metadata<br/>[metadata.py]"]
  node_transform["Record transform<br/>[transform.py]"]
  node_state["Bookmarks and state<br/>[state.py]"]
  node_bookmarks["Bookmark compatibility<br/>[bookmarks.py]"]
  node_state_diff["State diff<br/>[statediff.py]"]
end

subgraph group_observability["Observability"]
  node_metrics["Metrics<br/>[metrics.py]"]
  node_logger["Logging<br/>[logger.py]"]
end

node_tap(("Tap application"))
node_stdout["Standard output"]

node_tap -->|"calls"| node_public
node_public -->|"exports"| node_message_api
node_public -->|"exports"| node_message_types
node_public -->|"exports"| node_catalog
node_public -->|"exports"| node_schema
node_public -->|"exports"| node_transform
node_public -->|"exports"| node_state
node_public -->|"exports"| node_metrics
node_public -->|"exports"| node_utils
node_public -->|"exports"| node_logger
node_message_api -->|"constructs"| node_message_types
node_message_api -->|"writes JSON"| node_stdout
node_catalog -->|"uses"| node_schema
node_catalog -->|"reads selection"| node_metadata
node_catalog -->|"reads sync marker"| node_bookmarks
node_bookmarks -->|"delegates"| node_state
node_transform -->|"reads field rules"| node_metadata
node_transform -->|"gets logger"| node_logger
node_utils -->|"loads catalog"| node_catalog
node_metrics -->|"gets logger"| node_logger
node_message_api -->|"gets logger"| node_logger

click node_public "https://github.com/singer-io/singer-python/blob/master/singer/__init__.py"
click node_message_api "https://github.com/singer-io/singer-python/blob/master/singer/messages.py"
click node_message_types "https://github.com/singer-io/singer-python/blob/master/singer/messages.py"
click node_catalog "https://github.com/singer-io/singer-python/blob/master/singer/catalog.py"
click node_schema "https://github.com/singer-io/singer-python/blob/master/singer/schema.py"
click node_metadata "https://github.com/singer-io/singer-python/blob/master/singer/metadata.py"
click node_transform "https://github.com/singer-io/singer-python/blob/master/singer/transform.py"
click node_state "https://github.com/singer-io/singer-python/blob/master/singer/state.py"
click node_bookmarks "https://github.com/singer-io/singer-python/blob/master/singer/bookmarks.py"
click node_state_diff "https://github.com/singer-io/singer-python/blob/master/singer/statediff.py"
click node_utils "https://github.com/singer-io/singer-python/blob/master/singer/utils.py"
click node_metrics "https://github.com/singer-io/singer-python/blob/master/singer/metrics.py"
click node_logger "https://github.com/singer-io/singer-python/blob/master/singer/logger.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_public,node_utils toneBlue
class node_message_api,node_message_types toneAmber
class node_catalog,node_schema,node_metadata,node_transform,node_state,node_bookmarks,node_state_diff toneMint
class node_metrics,node_logger toneRose
class node_tap,node_stdout toneIndigo
```

## Components

### Public API

- [Library facade](https://github.com/singer-io/singer-python/blob/master/singer/__init__.py): `singer/__init__.py`
- [Tap utilities](https://github.com/singer-io/singer-python/blob/master/singer/utils.py): `singer/utils.py`

### Singer Messages

- [Message writers](https://github.com/singer-io/singer-python/blob/master/singer/messages.py): `singer/messages.py`
- [Message types](https://github.com/singer-io/singer-python/blob/master/singer/messages.py): `singer/messages.py`

### Sync Support

- [Catalog model](https://github.com/singer-io/singer-python/blob/master/singer/catalog.py): `singer/catalog.py`
- [Schema model](https://github.com/singer-io/singer-python/blob/master/singer/schema.py): `singer/schema.py`
- [Field metadata](https://github.com/singer-io/singer-python/blob/master/singer/metadata.py): `singer/metadata.py`
- [Record transform](https://github.com/singer-io/singer-python/blob/master/singer/transform.py): `singer/transform.py`
- [Bookmarks and state](https://github.com/singer-io/singer-python/blob/master/singer/state.py): `singer/state.py`
- [Bookmark compatibility](https://github.com/singer-io/singer-python/blob/master/singer/bookmarks.py): `singer/bookmarks.py`
- [State diff](https://github.com/singer-io/singer-python/blob/master/singer/statediff.py): `singer/statediff.py`

### Observability

- [Metrics](https://github.com/singer-io/singer-python/blob/master/singer/metrics.py): `singer/metrics.py`
- [Logging](https://github.com/singer-io/singer-python/blob/master/singer/logger.py): `singer/logger.py`

### Other components

- **Tap application**
- **Standard output**

## Connections

- Tap application → Library facade: calls
- Library facade → Message writers: exports
- Library facade → Message types: exports
- Library facade → Catalog model: exports
- Library facade → Schema model: exports
- Library facade → Record transform: exports
- Library facade → Bookmarks and state: exports
- Library facade → Metrics: exports
- Library facade → Tap utilities: exports
- Library facade → Logging: exports
- Message writers → Message types: constructs
- Message writers → Standard output: writes JSON
- Catalog model → Schema model: uses
- Catalog model → Field metadata: reads selection
- Catalog model → Bookmark compatibility: reads sync marker
- Bookmark compatibility → Bookmarks and state: delegates
- Record transform → Field metadata: reads field rules
- Record transform → Logging: gets logger
- Tap utilities → Catalog model: loads catalog
- Metrics → Logging: gets logger
- Message writers → Logging: gets logger
