Two Python floors, two package names, and a proprietary license field: inside soda-core
Data Contracts engine for the modern data stack. https://www.soda.io
At a glance
- What is it?
- soda-core is a Python engine for data quality contracts written in YAML, shipped as one package per data source across a fourteen member workspace. The CLI surface is small and legible. The version story around it is where the confusion sits.
- Who is it for?
- soda-core is worth a look if you want data quality checks expressed as YAML and checked from a pipeline step rather than from a UI. Three things to settle before you commit.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Two Python floors that disagree with each other
The requirements section says a user needs Python 3.9, 3.10, 3.11 or 3.12, and adds that 3.12 is the highest officially supported version while nothing is known to prevent 3.13 and newer. Further down, the development prerequisites say Python 3.10 or newer. The workspace manifest settles it in favour of the developer floor: `requires-python = ">=3.10"`. So a reader who trusts the first section and installs on 3.9 gets a package whose metadata excludes the interpreter they are on, and the front page never says which of the two numbers the packages actually enforce. The package manager has a floor too: uv is recommended, pip 21.0 or newer is the alternative, `python --version` or `python3 --version` is how you check, and pyenv is the suggestion for juggling interpreters.
One token separates the current package from the legacy one
Version 4 installs as `soda-` plus the data source name:
uv pip install soda-postgres # install latest version 4 packageThe legacy line inserts a word:
uv pip install soda-core-postgres~=3.5.0 # install legacy version 3 package (using UV)
# or
pip install soda-core-postgres~=3.5.0 # install legacy version 3 package (using pip)Both spellings resolve on public PyPI, and the v3 example is pinned to a 3.5 series. `soda-postgres` and `soda-core-postgres` differ by one hyphenated token, so a typo or a stale internal runbook installs two major versions of the same tool with no error at install time. The v3 documentation is also the one document set that stays in this repository, addressed to a v3 branch, with the v3 README and the Soda v3 site alongside it, while the default branch carries v4.
A fourteen member workspace where twelve are data sources
The repository is one workspace with fourteen members in the uv configuration: soda-core, soda-tests, and twelve data source packages named soda-athena, soda-bigquery, soda-databricks, soda-duckdb, soda-fabric, soda-postgres, soda-redshift, soda-snowflake, soda-sparkdf, soda-sqlserver, soda-synapse and soda-trino. Each of the twelve is also a top level directory, and each appears in the uv sources block as `workspace = true`. Only soda-postgres is named in the instructions, with one sentence telling you to replace the suffix for your own source. The front page claims checks on PostgreSQL, Snowflake, BigQuery, Databricks, DuckDB and more, so the six it names are a subset of what ships. The command surface is three verbs, `data-source create`, `data-source test` and `contract verify`, and every one of them needs a path flag.
The manifest says Proprietary, the metadata says nothing, the front page says open source
Three signals about licensing point in three directions. The repository metadata reports the license as NOASSERTION, meaning no value at all. The workspace manifest declares `license = {text = "Proprietary"}` for the root project. The front page states that the repository hosts the open source Soda Core packages installable from a public PyPI flow, and a LICENSE file sits at the root. No line anywhere reconciles them, and this is not a detail to skim: it decides whether a copy of the tool inside your own pipeline is something you can read and modify. Read the LICENSE file at the root and settle it before you vendor any of it.
The workspace sits on a release candidate the releases page does not show
The version field in the workspace manifest reads 4.25.1rc0. The three most recent tags are v4.25.0 on 2026-09-23, v4.24.0 on 2026-09-15 and v4.23.1 on 2026-09-08. The default branch is therefore one patch ahead of the newest release and carries a release candidate suffix, which is ordinary for a project that tags from a branch but means the branch version and the installable version are never the same string. A tbump.toml at the root is what moves the number. The repository has 2,432 stars, 289 forks and 212 open issues, so the issue count is not small next to the release cadence of roughly one tag a week across those three releases.
make release passes an empty argument unless you supply the version
The whole Makefile is three lines: a `.PHONY: release` declaration, the target, and a recipe reading `./scripts/release.sh $(version)`. That variable is never assigned anywhere in the file, so a bare `make release` hands the script an empty argument and only `make release version=4.25.0` passes anything. There is no target for tests, lint, or building a single package. The front page sends those to `uv run pytest soda-tests/` and `uv run pre-commit run --all-files`, and the pip alternative for setting up a working copy is `python -m venv .venv`, then `pip install -e soda-core -e soda-tests -e soda-postgres` with a note to add other packages as needed.
isort and black wrap at different widths on purpose
The manifest configures isort with `profile = "black"` and then carries a comment explaining the trap in detail. The black profile sets line_length to 88 and does not read the black configuration, so without an explicit line length in the isort section, isort wraps imports at 88 while black is content up to 120. The comment's conclusion is that a hundred character import passes black and fails isort. The dev group pins black at 26.1.0 or newer alongside pytest, pre-commit, tbump, pydantic, python-dotenv and freezegun, then adds polars, pandas and pyarrow for test fixtures. The root also carries pytest.ini, a .pre-commit-config.yaml and a .env_example, so configuration for contributors lives in the repository rather than in a wiki.
A verification run needs two files and one qualified name
The contract language is YAML with checks at dataset level and at column level. This example tests a table or view addressed as `postgres_ds/db/schema/dataset` inside a data source named `postgres_ds`:
dataset: postgres_ds/db/schema/dataset
checks: # dataset level checks
- schema:
- row_count:
columns: # columns block
- name: id
checks: # column level checks
- missing:
- name: name
checks:
- missing:
threshold:
metric: percent
must_be_less_than: 10
- name: size
checks:
- invalid:
valid_values: ['S', 'M', 'L']Running it locally takes both files at once, with `--verbose` or `-v` added to any command for detailed logs:
soda contract verify -ds ds_config.yml -c contract.ymlThe data source name in the contract has to match the name property in the data source configuration, and the generated `ds_config.yml` is a PostgreSQL template by default, so a verification run against another engine starts by editing that file. The generated configuration itself comes from `soda data-source create -f ds_config.yml`.
Editorial conclusion
soda-core is worth a look if you want data quality checks expressed as YAML and checked from a pipeline step rather than from a UI. Three things to settle before you commit. Work out which major version you are on, because the v3 and v4 package names differ by one token and both resolve on public PyPI, so the wrong one installs silently. Read the license file yourself, since the repository metadata reports no value, the workspace manifest declares the text Proprietary, and the front page calls the packages open source. And pick a Python version deliberately, because the front page lists 3.9 for users while the workspace manifest requires 3.10 or newer. The last recorded push is 2026-10-02 and the newest tag is v4.25.0, so the v4 line is the one still moving.
Frequently asked questions
what is soda core
It is a data quality and data contract verification engine that lets you define contracts in YAML and validate schema and data automatically. It ships a command line interface and a Python API, and the operations can run locally, inside pipelines such as Airflow, Dagster or Prefect, or remotely when connected to Soda Cloud.
how to use soda core
Install the package for your data source, such as soda-postgres, then create a data source configuration with soda data-source create -f ds_config.yml and check it with soda data-source test -ds ds_config.yml. Write a contract YAML file and run soda contract verify -ds ds_config.yml -c contract.yml.
is soda core open source
The front page states that the repository hosts the open source Soda Core packages and installs them from public PyPI, and a LICENSE file sits at the root. The licensing signals conflict, because the repository metadata reports NOASSERTION and the workspace manifest declares the license text as Proprietary.
is soda core free
Installation comes from public PyPI with either uv or pip 21.0 and newer, and the page lists no price for anything. It does point at Soda Cloud for centralized management and anomaly detection monitoring, which is a separate service, and gives no figure for it.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/sodadata-soda-core)