Hard sources — not covered by free tools
Also parsed — certify what free tools miss
Runtimes
After migration
Parser-driven modernization of Talend project exports, Git workspaces, and .item artifacts — Standard Jobs, tMap logic, contexts, and metadata connections. Full lineage, automated conversion, validated parity.
Talend job parsed into interactive lineage graph
One source, every target. Deterministic parsers read the estate and emit native code for the platform you pick — not Talend jobs re-pointed at a cloud warehouse.
Talend estate → MigryX parser → native platforms
Deterministic parseAI where it helpsThe parser is deterministic: the same input produces the same output on every run. Every output is validated against the original, row by row, before go-live.
Teams that standardised on the free edition have no supported upgrade path and no security patches. That converts a tool that was chosen because it cost nothing into an unbudgeted subscription or a migration.
A Talend job compiles to Java. Debugging production means reading generated code, and the canvas is the only place the intent exists. That coupling is what makes jobs hard to review, test, or port.
TAC, JobServers or Remote Engines, plus a project repository, all have to be kept available and patched. On modern platforms the orchestrator and compute are managed services, so that tier disappears.
A single tMap doing an inner join, a lookup, derived expressions, a filtered output and a reject output. Everything meaningful about the job is inside one component's configuration, which is why exporting the canvas is not the same as understanding it.
-- Job: LOAD_ORDER_FACT Component: tMap_1
Main input : row1 (ORDERS)
Lookup input : row2 (CUSTOMER) join model: inner
row2.CUST_ID = row1.CUST_ID
match model: unique match
Var.margin = row1.REVENUE - row1.COST
Var.tier = row2.TIER_CODE == null
? "UNKNOWN" : row2.TIER_CODE
Output "out_valid" filter: Var.margin >= 0
ORDER_ID = row1.ORDER_ID
FULL_NAME = row2.FIRST_NM + " " + row2.LAST_NM
MARGIN = Var.margin
TIER = Var.tier
Output "out_reject" (catch lookup inner join reject)
ORDER_ID = row1.ORDER_ID
REASON = "customer not found"
# tMap → join, derived columns, split outputs
from pyspark.sql import functions as F
joined = orders.join(customer, "cust_id", "left")
enriched = (
joined
.withColumn("margin", F.col("revenue") - F.col("cost"))
.withColumn("tier",
F.coalesce("tier_code", F.lit("UNKNOWN")))
)
# inner-join reject captured, not discarded
out_reject = (
enriched.filter(F.col("cust_id_lookup").isNull())
.select("order_id",
F.lit("customer not found").alias("reason"))
)
out_valid = (
enriched.filter(F.col("cust_id_lookup").isNotNull()
& (F.col("margin") >= 0))
.select("order_id",
F.concat_ws(" ", "first_nm", "last_nm")
.alias("full_name"),
"margin", "tier")
)
The tMap variables become derived columns, the inner-join semantics become an explicit null test, and the reject output survives as its own DataFrame instead of being lost when the component is rebuilt by hand.
Every Talend component in your jobs maps to a defined target equivalent, recorded in the lineage report.
| Talend Component | Target Equivalent | Notes |
|---|---|---|
| tMap | Join, derived columns, split outputs | Variables, filters and reject flows preserved |
| tFilterRow | .filter() / WHERE | Compound conditions parsed |
| tJoin | .join() | Join model and match model mapped |
| tAggregateRow | .groupBy().agg() | Group keys and aggregate operations |
| tSortRow / tUniqRow | .orderBy(), dedupe | Sort keys and uniqueness columns |
| tDBInput / tDBOutput | Table read and write | Action on data mapped to insert or upsert |
| tFileInput / tFileOutput | File read and write | Delimiters, encoding and header settings |
| tRunJob / child job | Reusable module or sub-task | Context propagation preserved |
| Joblet | Reusable function | Inlined or emitted once per reference |
| Context / context group | Parameters and environment config | Per-environment values kept separate |
| tJava / tJavaRow | Extracted code with review report | Embedded Java reported, not silently converted |
| Metadata connection | Connection config and secrets | Repository metadata resolved to targets |
| tDie / tWarn / reject links | Explicit error branches | Failure paths kept as real branches |
MigryX Data Matching compares Talend job output against the new pipeline output, row by row and column by column, with configurable tolerance rules and mismatch drill-down.
See how Data Matching works →A project export (ZIP) from Studio, or the Git workspace containing the .item and .properties files. The .item files hold the component configuration, including tMap expressions, so they are the substantive input rather than the compiled Java.
The job definition. Generated Java is an artifact of the build and reflects Talend's runtime rather than your intent, so parsing the component graph produces cleaner and more reviewable target code.
Custom Java is extracted and reported with the jobs that use it instead of being machine-translated, because that code frequently reaches outside the job into shared libraries or environment assumptions that a parser cannot verify.
No. Parsing works from the project export or workspace files, so it does not require a supported subscription, a TAC instance, or a running JobServer. This is the common case for teams whose free edition reached end of life.