Skip to content

Linkuity

CILicense.NET

Open-source entity resolution and golden-record engine.

Linkuity finds the records that refer to the same person or organization, links them into clusters, and merges each cluster into one explainable golden record — all inside your own environment.

  • 🔍 Detect duplicates across CSVs, systems, and incremental loads
  • 🧩 Build golden records with source-aware merge rules
  • 🧠 Explain every match with per-field score breakdowns
  • 🔒 Run locally or privately — no customer data leaves your environment
  • ♻️ Batch or durable incremental resolution as data arrives over time

Linkuity resolving 28 source records into 10 golden records

Quick start

Prerequisites:.NET 10 SDK.

Resolve the bundled 28-record sample into golden records:

git clone https://github.com/linkuity/linkuity.git
cd linkuity
dotnet run --project src/Linkuity.Cli -- run `--input samples/people-multi-source/sample.csv `--profile samples/people-multi-source/people-multi-source.profile.json `--merge-policy samples/people-multi-source/people-multi-source.merge.json `--output ./data/output/people-multi-source
Job 5f3a…c21e completed.
Golden records: …/data/output/people-multi-source/golden-records.csv

28 source records from CRM, Marketing, Support, and Billing → 10 golden records. Add --neo4j-export to also write a graph bundle. Next: the guided durable MDM quick start.

The demo above is generated from docs/assets/demo.tape by the Demo GIF workflow — see docs/assets.

Before and after

Real systems rarely store a person the same way twice — a nickname here, a typo there, a phone number in a different format:

idsourcefirst_namelast_nameemailphoneaddress_line
crm-050CRMJosephMartinezjoseph.martinez@example.com(312) 555-01471420 Maple Avenue
mkt-051MarketingJoeMartinezjoe.martinez@example.com312-555-01471420 Maple Ave
sup-052SupportJoesphMartinezjoseph.martinez@example.com312.555.01471420 Maple Avenue Apt 3B
bil-053BillingJosephMartinezjoseph.martimez@example.com31255501471420 Maple Ave Apt 3B

Every mismatch is one you have probably seen in production: a nickname (Joe), a misspelling (Joesph), a one-letter email typo (martimez), one phone in four formats, and an apartment number that only reached two systems.

Linkuity normalizes, blocks, scores, and clusters these into a single golden record:

record_countmember_idsfirst_nameemailphoneaddress_line
4crm-050|mkt-051|sup-052|bil-053Josephjoseph.martinez@example.com+131255501471420 Maple Ave Apt 3B

And it is explainablefirst_name wins by consensus (Joseph over the nickname and the typo), email by CRM source priority (the typo-free address), phone normalizes to one number, and address takes the Billing row with the unit. A golden record is a composite, not a copy of any single row. See how matching works and the people-multi-source sample.

Why Linkuity

Most ways to resolve entities fall into one of three buckets, each with a catch: hosted matching services (you ship customer data to someone else's cloud), closed-source products (you can't inspect or tune how matches are decided), and low-level fuzzy-matching libraries (powerful, but you assemble blocking, scoring, clustering, merging, and persistence yourself).

Linkuity is a complete, open-source engine you run yourself:

Hosted serviceClosed productMatch libraryLinkuity
Open source
Data stays in your environmentvaries
Explainable match decisionsvariesyou build it
Whole workflow (merge, golden records, persistence)
Durable incremental resolutionvariesvaries
Native .NET, cross-platformvaries

Common use cases

  • Customer 360 / MDM — one trusted record per customer from many systems
  • CRM cleanup & contact deduplication — collapse duplicate people
  • Supplier / vendor consolidation — dedupe and standardize organizations
  • Organization resolution — match companies across name and domain variants
  • Data migrations — dedupe before loading into a new system
  • Incremental identity resolution — keep records linked as new data lands
  • Graph analysis — export resolved entities to Neo4j and explore the links

How it works

flowchart TD
A[CSV / sources] --> B[Normalization]
B --> C[Blocking]
C --> D[Candidate retrieval]
D --> E[Scoring]
E --> F[Decision bands]
F --> G[Clustering]
G --> H[Golden records]
H --> I[Exports & review]
Loading

Comparing every record against every other is and doesn't scale, so Linkuity only scores candidate pairs that share a cheap blocking key, combines per-field similarities into one score, and sorts each pair into a decision band: auto-merge, review, or no-match. Accepted pairs cluster transitively, and each cluster merges into a golden record via your source-priority rules — with a per-field breakdown you can read back. Full detail (with a worked example): how-matching-works.md.

Batch mode vs durable mode

Batch modeDurable mode
Entry pointlinkuity runlinkuity project / ingest-incremental
StateStateless — resolves and forgetsPersistent store that remembers
New dataReprocesses the whole fileMatched incrementally against stored records
History & reviewVersioned golden records + review queue
Store backendOutput filesLocal JSON file or PostgreSQL
Reach for it whenOne-off dedupe, exports, CIOngoing MDM as data arrives over time

The quick start uses batch mode. For durable mode, follow the durable MDM quick start; to back it with PostgreSQL, see durable-postgres.md.

Key capabilities

  • Matching engine — normalization, blocking (including phonetic), weighted similarity scoring, Lucene-backed candidate retrieval
  • Taxonomy-driven — ships person and organization built in; a new content type (e.g. the location sample) is a config-only *.profile.json, no code change — see docs/configuration.md
  • Explainability — persisted per-field score breakdowns and read-back commands
  • Golden records — configurable source-priority merge policies; composite output
  • Two modes — stateless batch and durable incremental (versioning + review queue)
  • Storage — local filesystem + JSON store, or a PostgreSQL durable backend
  • InterfacesCLI, HTTP API, and Docker Compose
  • Graph export — Neo4j-ready node/relationship bundle
  • Runtime — native .NET 10; cross-platform and single-file deployable
  • License — Apache 2.0

Showcases and samples

The samples/ directory has small, self-contained datasets — each with a walkthrough and test-pinned expected results — covering multi-source people and organization merging, unreliable-field handling, name noise, and durable incremental scenarios. Start with people-multi-source (the 28 → 10 example above).

For a full end-to-end demo on real public data, see showcases/company-resolution — resolve real companies across multiple public data sources.

Documentation

Roadmap

Active development. Near-term focus (full plan in docs/roadmap/PLAN.md):

  • Packaged CLI releases so users don't build from source
  • More realistic sample datasets
  • Reproducible quality/cost benchmarks (plan)
  • Better match explanations and review workflows
  • SDK, connector, and plugin guidance
  • Larger-scale private-server deployment examples

Contributing

Contributions are welcome. Start with CONTRIBUTING.md, which covers development setup and the Contributor License Agreement (CLA.md). Please also review CODE_OF_CONDUCT.md, SECURITY.md, and CHANGELOG.md.

License

Linkuity is licensed under the Apache License 2.0.

About

Linkuity is a golden-record engine for data and MDM teams

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages