Download index.html from getreadystack/pekko-migration-gate: direct link, hf CLI and curl.
- Browser
- Download file 47.9 kB
-
https://huggingface.co/spaces/getreadystack/pekko-migration-gate/resolve/main/index.html
- Command line
-
hf download hf://spaces/getreadystack/pekko-migration-gate/index.html
-
curl -L -o index.html https://huggingface.co/spaces/getreadystack/pekko-migration-gate/resolve/main/index.html
47.9 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width,initial-scale=1"> | |
| <title>Pekko Akka Migration check — check dependencies before pekko migration</title> | |
| <meta name="description" content="This free browser tool checks build and configuration files for Akka BSL 1.1 jars, akka configuration, seeds, and ports Pekko ignores."> | |
| <style> | |
| :root{color-scheme:light}body{margin:0;font:15px/1.55 system-ui,-apple-system,"Segoe UI",sans-serif;background:#faf9f5;color:#1a1512} | |
| .wrap{max-width:960px;margin:0 auto;padding:28px 18px 60px}h1{font-size:26px;margin:0 0 6px}.lede{color:#4a403a;margin:0 0 16px} | |
| textarea{width:100%;min-height:260px;font:13px/1.45 ui-monospace,Menlo,Consolas,monospace;padding:12px;border:1px solid #d9d0c4;border-radius:8px;box-sizing:border-box} | |
| .bar{display:flex;gap:10px;align-items:center;margin:12px 0}button{font:600 15px system-ui;padding:10px 18px;border:0;border-radius:8px;background:#1a1512;color:#fff;cursor:pointer} | |
| input[type=date]{font:14px system-ui;padding:8px;border:1px solid #d9d0c4;border-radius:6px} | |
| table{border-collapse:collapse;width:100%;font-size:14px;margin-top:10px}th,td{text-align:left;padding:8px 10px;border-bottom:1px solid #eee;vertical-align:top}th{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:#7a6e65} | |
| .sev.error{color:#a8551f;font-weight:700}.sev.warn,.sev.warning{color:#96691f}.ok{color:#2a6446;font-weight:600}.sum{font-weight:600} | |
| .note{font-size:13px;color:#7a6e65;margin-top:18px}#paid{margin-top:22px;padding:14px 16px;border:1px solid #e2d8cb;border-radius:10px;background:#fffdfa} | |
| </style> | |
| <script data-grow-initializer="">!(function(){window.growMe||((window.growMe=function(e){window.growMe._.push(e);}),(window.growMe._=[]));var e=document.createElement("script");(e.type="text/javascript"),(e.src="https://faves.grow.me/main.js"),(e.defer=!0),e.setAttribute("data-grow-faves-site-id","U2l0ZTphZjljMzgyMC0yMmU5LTRhYjgtYTIxNS03OTRhMGY1N2ExYzM=");var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t);})();</script> | |
| <!--yj-canon-s101--><link rel="canonical" href="https://getreadystack.com/tools/pekko-migration-gate"></head> | |
| <body> | |
| <div class="wrap"> | |
| <h1>Pekko Akka Migration check — check dependencies before pekko migration</h1> | |
| <p class="lede">Pekko migration check for build.sbt, pom.xml, build.gradle and application.conf: flags Akka jars still under BSL 1.1 on a given date, akka.* config, akka:// seeds and ports Pekko ignores. Runs entirely in your browser — nothing is uploaded.</p> | |
| <textarea id="src" spellcheck="false">// build.sbt — order-service, halfway through the Pekko move | |
| ThisBuild / scalaVersion := "2.13.14" | |
| val AkkaVersion = "2.9.3" | |
| val AkkaHttpVersion = "10.5.3" | |
| libraryDependencies ++= Seq( | |
| "com.typesafe.akka" %% "akka-actor-typed" % AkkaVersion, | |
| "com.typesafe.akka" %% "akka-stream" % AkkaVersion, | |
| "com.typesafe.akka" %% "akka-http" % AkkaHttpVersion, | |
| "com.lightbend.akka" %% "akka-stream-alpakka-s3" % "6.0.2", | |
| "com.typesafe.akka" %% "akka-stream-kafka" % "4.0.2", | |
| "org.apache.pekko" %% "pekko-connectors-csv" % "1.0.2", | |
| "ch.qos.logback" % "logback-classic" % "1.5.6" | |
| )</textarea> | |
| <div class="bar"><button id="go">Check</button><label>as of <input type="date" id="today"></label></div> | |
| <div id="out" aria-live="polite"></div> | |
| <div id="paid"><strong>Free here:</strong> Checks the open build or config file: every Akka jar still under BSL 1.1 on your date, every akka.* key, akka:// seed and old port Pekko ignores, with the Pekko line to paste. <strong>In the editor:</strong> Workspace sweep: every build.sbt, pom.xml, build.gradle and .conf in the repo in one Markdown migration report for your licence owner. — that part asks for a licence key.</div> | |
| <p id="buy"><a href="https://getreadystack.com/api/buy/cl/polar_cl_31Zz7p4BZ19GYaxA6IFbSWHcVy77keudb2iZg2eBMSt">Get the full version — $29</a> · $29 once · one licence key per person or team seat. Akka subscriptions start at $0.25 per core hour.</p> | |
| <p class="note">Same engine as the VS Code extension, byte for byte.</p> | |
| </div> | |
| <script>var PEKKO_RULES = [ | |
| {"id": "akka-core-bsl-active", "sev": "error", "title": "Akka core jar still under BSL 1.1 on this date", | |
| "why": "Akka 2.7.0 and later ship under the Business Source License 1.1. Each release converts to Apache 2.0 only on its own Change Date, printed in that release's LICENSE file. Production use before that date needs a commercial Akka licence unless a grant applies.", | |
| "fix": "Replace com.typesafe.akka with org.apache.pekko and akka-* with pekko-* (Pekko 1.x, Apache 2.0).", | |
| "source": "LICENSE files in github.com/akka/akka at tags v2.8.0, v2.8.8, v2.9.0, v2.9.5, v2.10.0", | |
| "change_dates": {"2.8.0": "2026-03-16", "2.8.8": "2027-10-28", "2.9.0": "2026-10-23", "2.9.5": "2027-08-19", "2.10.0": "2027-10-16"}, | |
| "line_min": {"2.8": "2026-03-16", "2.9": "2026-10-23", "2.10": "2027-10-16"}}, | |
| {"id": "akka-core-bsl-unresolved", "sev": "warning", "title": "Akka core jar under BSL, Change Date not proven for this exact release", | |
| "why": "Patch releases carry their own Change Date, three years after that release. Akka 2.8.0 turned Apache 2.0 on 2026-03-16 but Akka 2.8.8 stays BSL until 2027-10-28. The 2.7.x LICENSE says 'TBD (3 years after 2.7.0 release)'.", | |
| "fix": "Read the LICENSE inside the exact jar version, or move to org.apache.pekko."}, | |
| {"id": "akka-core-converted", "sev": "info", "title": "This exact Akka release has passed its Change Date", | |
| "why": "On its Change Date the release converts to Apache 2.0. Any later patch you upgrade to is BSL again.", | |
| "fix": "Pin this exact version, or move to org.apache.pekko before you upgrade."}, | |
| {"id": "akka-module-bsl-line", "sev": "warning", "title": "Akka module on a BSL release line", | |
| "why": "The Akka 22.10 release moved these modules to BSL 1.1: Akka HTTP 10.4.0, Akka gRPC 2.2.0, Akka Management 1.2.0, Alpakka Kafka 4.0.0, Alpakka 5.0.0, Akka Persistence R2DBC 1.0.0, Akka Persistence JDBC 5.2.0, Akka Persistence Cassandra 1.1.0, Akka Projections 1.3.0.", | |
| "fix": "Use the Apache Pekko module named in the message.", | |
| "modules": [ | |
| {"match": "^akka-http", "from": "10.4.0", "line": "Akka HTTP", "pekko": "pekko-http"}, | |
| {"match": "^akka-stream-kafka", "from": "4.0.0", "line": "Alpakka Kafka", "pekko": "pekko-connectors-kafka"}, | |
| {"match": "^akka-stream-alpakka-", "from": "5.0.0", "line": "Alpakka", "pekko": "pekko-connectors-"}, | |
| {"match": "^akka-grpc", "from": "2.2.0", "line": "Akka gRPC", "pekko": "pekko-grpc"}, | |
| {"match": "^akka-(management|discovery-(kubernetes|aws|consul|marathon)|lease-kubernetes|rolling-update)", "from": "1.2.0", "line": "Akka Management", "pekko": "pekko-management"}, | |
| {"match": "^akka-persistence-jdbc", "from": "5.2.0", "line": "Akka Persistence JDBC", "pekko": "pekko-persistence-jdbc"}, | |
| {"match": "^akka-persistence-cassandra", "from": "1.1.0", "line": "Akka Persistence Cassandra", "pekko": "pekko-persistence-cassandra"}, | |
| {"match": "^akka-persistence-r2dbc", "from": "1.0.0", "line": "Akka Persistence R2DBC", "pekko": "pekko-persistence-r2dbc"}, | |
| {"match": "^akka-projection", "from": "1.3.0", "line": "Akka Projections", "pekko": "pekko-projection"}]}, | |
| {"id": "akka-pekko-mixed", "sev": "error", "title": "Akka and Pekko jars in the same build", | |
| "why": "A half-finished move keeps the BSL jars on the classpath and runs two actor toolkits side by side.", | |
| "fix": "Finish the swap: no com.typesafe.akka or com.lightbend.akka coordinates left."}, | |
| {"id": "akka-config-ignored", "sev": "error", "title": "akka.* config key that Pekko never reads", | |
| "why": "Pekko reads its settings from the pekko.* namespace. An akka { } block is silently ignored, so settings such as actor.provider = cluster fall back to defaults.", | |
| "fix": "Rename the root key from akka to pekko."}, | |
| {"id": "akka-seed-protocol", "sev": "error", "title": "akka:// address that a default Pekko node refuses", | |
| "why": "pekko.remote.protocol-name defaults to pekko and accept-protocol-names defaults to [\"pekko\"].", | |
| "fix": "Write pekko://, or during a rolling move set pekko.remote.accept-protocol-names = [\"akka\", \"pekko\"]."}, | |
| {"id": "akka-default-port", "sev": "warning", "title": "Akka default remoting port", | |
| "why": "Akka defaults to 25520 (Artery) and 2552 (classic). Pekko defaults to 17355 (Artery) and 7355 (classic), so a node that relied on the default listens on a different port after the swap.", | |
| "fix": "Set pekko.remote.artery.canonical.port explicitly, or change the seed address to 17355."}, | |
| {"id": "akka-import", "sev": "warning", "title": "import akka.* in source", | |
| "why": "Pekko classes live under org.apache.pekko; import akka.* will not compile once the Akka jars are gone.", | |
| "fix": "Rewrite the import to org.apache.pekko."} | |
| ] | |
| ;</script> | |
| <script>// Pekko Migration Gate — one engine for the VS Code extension and the free web page. | |
| (function () { | |
| const RULES = (typeof module !== 'undefined') ? require('./rules.json') : window.PEKKO_RULES; | |
| const R = {}; RULES.forEach(r => { R[r.id] = r; }); | |
| const CORE = R['akka-core-bsl-active']; | |
| const MODULES = R['akka-module-bsl-line'].modules.map(m => Object.assign({ re: new RegExp(m.match) }, m)); | |
| const AKKA_GROUP = /^com\.(typesafe|lightbend)\.akka(\.[\w.]+)?$/; | |
| const PEKKO_GROUP = 'org.apache.pekko'; | |
| function vparts(v) { return String(v).split(/[.\-]/).map(x => parseInt(x, 10)).filter(n => !isNaN(n)); } | |
| function vcmp(a, b) { | |
| const x = vparts(a), y = vparts(b); | |
| for (let i = 0; i < Math.max(x.length, y.length); i++) { | |
| const d = (x[i] || 0) - (y[i] || 0); | |
| if (d) return d < 0 ? -1 : 1; | |
| } | |
| return 0; | |
| } | |
| function pekkoName(artifact, mod) { | |
| if (!mod) return artifact.replace(/^akka-/, 'pekko-'); | |
| if (mod.pekko.endsWith('-')) return artifact.replace(mod.re, mod.pekko); | |
| return artifact.replace(/^akka-[a-z]+(-[a-z]+)?/, m => m.startsWith('akka-stream-kafka') ? mod.pekko : m.replace(/^akka-/, 'pekko-')); | |
| } | |
| function pekkoLine(artifact, mod) { | |
| return '"org.apache.pekko" %% "' + pekkoName(artifact, mod) + '" % <Pekko 1.x version>'; | |
| } | |
| function collectVars(lines) { | |
| const vars = {}; | |
| lines.forEach(l => { | |
| let m; | |
| const a = /\b([A-Za-z_][\w]*)\s*=\s*["']([0-9][\w.\-]*)["']/.exec(l); | |
| if (a) vars[a[1]] = a[2]; | |
| const re = /<([\w.\-]+)>([0-9][\w.\-]*)<\/\1>/g; | |
| while ((m = re.exec(l))) vars[m[1]] = m[2]; | |
| }); | |
| return vars; | |
| } | |
| function resolve(tok, vars) { | |
| if (!tok) return null; | |
| const t = tok.replace(/^\$\{?|\}$/g, ''); | |
| if (/^[0-9]/.test(t)) return t; | |
| return vars[t] || null; | |
| } | |
| function findDeps(lines, vars) { | |
| const deps = []; | |
| const sbt = /"([\w.]+)"\s*%{1,3}\s*"([\w.\-]+)"\s*%\s*(?:"([^"]+)"|([A-Za-z_]\w*))/g; | |
| const gradle = /["']([\w.]+):([\w.\-]+?)(?:_[23](?:\.\d+)?)?:([^"':]+)["']/g; | |
| lines.forEach((l, i) => { | |
| let m; | |
| sbt.lastIndex = 0; | |
| while ((m = sbt.exec(l))) deps.push({ group: m[1], artifact: m[2].replace(/_[23](\.\d+)?$/, ''), version: resolve(m[3] || m[4], vars), raw: m[3] || m[4], line: i + 1 }); | |
| gradle.lastIndex = 0; | |
| if (!/%/.test(l)) while ((m = gradle.exec(l))) deps.push({ group: m[1], artifact: m[2], version: resolve(m[3], vars), raw: m[3], line: i + 1 }); | |
| const g = /<groupId>\s*([\w.]+)\s*<\/groupId>/.exec(l); | |
| if (g) { | |
| let artifact = null, aline = i + 1, ver = null, raw = null; | |
| for (let j = Math.max(0, i - 3); j < Math.min(lines.length, i + 7); j++) { | |
| if (j > i && /<\/(dependency|plugin)>/.test(lines[j])) break; | |
| const a = /<artifactId>\s*([\w.\-]+)\s*<\/artifactId>/.exec(lines[j]); | |
| if (a && !artifact) { artifact = a[1].replace(/_[23](\.\d+)?$/, ''); aline = j + 1; } | |
| const v = /<version>\s*([^<\s]+)\s*<\/version>/.exec(lines[j]); | |
| if (v && j >= i) { raw = v[1]; ver = resolve(v[1], vars); } | |
| } | |
| if (artifact) deps.push({ group: g[1], artifact, version: ver, raw, line: aline }); | |
| } | |
| }); | |
| return deps; | |
| } | |
| function coreFinding(d, today) { | |
| const v = d.version, p = vparts(v); | |
| const line = p[0] + '.' + p[1]; | |
| const exact = CORE.change_dates[v]; | |
| const to = pekkoLine(d.artifact); | |
| if (exact) { | |
| if (today < exact) return { check: 'akka-core-bsl-active', sev: 'error', msg: d.artifact + ' ' + v + ' is BSL 1.1 until ' + exact + ' → ' + to }; | |
| return { check: 'akka-core-converted', sev: 'info', msg: d.artifact + ' ' + v + ' turned Apache 2.0 on ' + exact + '; any later patch is BSL again → pin it or ' + to }; | |
| } | |
| if (p[0] === 2 && p[1] === 7) return { check: 'akka-core-bsl-unresolved', sev: 'warning', msg: d.artifact + ' ' + v + ': the 2.7.x LICENSE gives Change Date "TBD (3 years after 2.7.0 release)" → confirm in the jar or ' + to }; | |
| const min = CORE.line_min[line]; | |
| if (!min && (p[0] > 2 || p[1] > 10)) return { check: 'akka-core-bsl-active', sev: 'error', msg: d.artifact + ' ' + v + ' is newer than 2.10.0, whose BSL runs until ' + CORE.change_dates['2.10.0'] + ' → ' + to }; | |
| if (min && today < min) return { check: 'akka-core-bsl-active', sev: 'error', msg: d.artifact + ' ' + v + ' is BSL 1.1 until at least ' + min + ' (the ' + line + '.0 Change Date; later patches convert later) → ' + to }; | |
| if (min) return { check: 'akka-core-bsl-unresolved', sev: 'warning', msg: d.artifact + ' ' + v + ': ' + line + '.0 converted on ' + min + ' but each patch has its own later date (2.8.8: 2027-10-28) → read its LICENSE or ' + to }; | |
| return null; | |
| } | |
| function check(text, opts) { | |
| opts = opts || {}; | |
| const today = String(opts.today || new Date().toISOString()).slice(0, 10); | |
| const lines = String(text || '').split(/\r?\n/); | |
| const vars = collectVars(lines); | |
| const findings = []; | |
| const deps = findDeps(lines, vars); | |
| let akkaSeen = null, pekkoSeen = null; | |
| deps.forEach(d => { | |
| if (d.group === PEKKO_GROUP) { if (!pekkoSeen) pekkoSeen = d; return; } | |
| if (!AKKA_GROUP.test(d.group) || !/^akka/.test(d.artifact)) return; | |
| if (!akkaSeen) akkaSeen = d; | |
| const mod = MODULES.find(m => m.re.test(d.artifact)); | |
| if (!d.version) { | |
| findings.push({ check: 'akka-core-bsl-unresolved', sev: 'warning', msg: d.artifact + ': version "' + (d.raw || '?') + '" is not set in this file, so its licence cannot be dated → ' + pekkoLine(d.artifact, mod), line: d.line }); | |
| return; | |
| } | |
| if (mod) { | |
| if (vcmp(d.version, mod.from) >= 0) findings.push({ check: 'akka-module-bsl-line', sev: 'warning', msg: mod.line + ' ' + d.version + ' is on the BSL line (from ' + mod.from + ') → ' + pekkoLine(d.artifact, mod), line: d.line }); | |
| return; | |
| } | |
| if (vcmp(d.version, '2.7.0') < 0) return; | |
| const f = coreFinding(d, today); | |
| if (f) { f.line = d.line; findings.push(f); } | |
| }); | |
| if (akkaSeen && pekkoSeen) findings.push({ check: 'akka-pekko-mixed', sev: 'error', msg: pekkoSeen.artifact + ' sits next to ' + akkaSeen.artifact + ' (line ' + akkaSeen.line + '): half-migrated build, the BSL jars are still shipped', line: pekkoSeen.line }); | |
| lines.forEach((l, i) => { | |
| const s = l.replace(/^\s+/, ''); | |
| if (/^(\/\/|#|\*)/.test(s) || /%|<groupId>|com\.typesafe|com\.lightbend/.test(l)) return; | |
| if (/^akka\s*(\{|\.[\w-])/.test(s)) findings.push({ check: 'akka-config-ignored', sev: 'error', msg: 'Pekko never reads "' + s.split(/\s*[{=:]/)[0].trim() + '" → rename the root to pekko', line: i + 1 }); | |
| if (/akka:\/\//.test(l)) findings.push({ check: 'akka-seed-protocol', sev: 'error', msg: 'akka:// address: a default Pekko node accepts only pekko:// → write pekko:// or set accept-protocol-names = ["akka", "pekko"]', line: i + 1 }); | |
| const port = /(?:port\s*[=:]\s*|:)(25520|2552)\b/.exec(l); | |
| if (port) findings.push({ check: 'akka-default-port', sev: 'warning', msg: 'Port ' + port[1] + ' is the Akka default; Pekko listens on ' + (port[1] === '25520' ? '17355' : '7355') + ' unless you set it', line: i + 1 }); | |
| if (/^import\s+akka[.{]/.test(s)) findings.push({ check: 'akka-import', sev: 'warning', msg: s.replace(/;$/, '') + ' → ' + s.replace(/^import\s+akka/, 'import org.apache.pekko').replace(/;$/, ''), line: i + 1 }); | |
| }); | |
| findings.sort((a, b) => a.line - b.line); | |
| return { findings }; | |
| } | |
| const api = { engine: { check }, RULES, RULE_COUNT: RULES.length }; | |
| if (typeof module !== 'undefined') module.exports = api; | |
| if (typeof window !== 'undefined') window.PEKKOENGINE = api; | |
| })(); | |
| </script> | |
| <script>// ⛔뼈대 — kit/scaffold.py 가 찍는다 (s143). findings [{check,sev,msg,line?}] → 글/HTML. 같은 파일이 Node 와 브라우저에서 산다. | |
| ; | |
| function escapeHtml(s) { return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); } | |
| function summaryLine(res) { | |
| const f = (res && res.findings) || []; const e = f.filter(function (x) { return String(x.sev || 'error').toLowerCase().startsWith('err'); }).length; | |
| return f.length ? (f.length + ' finding' + (f.length === 1 ? '' : 's') + ' (' + e + ' error' + (e === 1 ? '' : 's') + ')') : 'Clean — no findings.'; | |
| } | |
| function toText(res, label) { | |
| const f = (res && res.findings) || []; | |
| const lines = ['== ' + (label || '') + ' — ' + summaryLine(res)]; | |
| f.forEach(function (x) { lines.push(' ' + String(x.sev || 'error').toUpperCase().slice(0, 4) + ' ' + (x.line ? 'L' + x.line + ' ' : '') + (x.check || x.id || '') + ' ' + (x.msg || x.message || '')); }); | |
| return lines.join('\n'); | |
| } | |
| function toHtml(res) { | |
| const f = (res && res.findings) || []; | |
| if (!f.length) return '<p class="ok">' + escapeHtml(summaryLine(res)) + '</p>'; | |
| const rows = f.map(function (x) { return '<tr><td class="sev ' + escapeHtml(String(x.sev || 'error')) + '">' + escapeHtml(String(x.sev || 'error')) + '</td><td>' + (x.line ? 'L' + escapeHtml(x.line) : '') + '</td><td><code>' + escapeHtml(x.check || x.id || '') + '</code></td><td>' + escapeHtml(x.msg || x.message || '') + '</td></tr>'; }).join(''); | |
| return '<p class="sum">' + escapeHtml(summaryLine(res)) + '</p><table><thead><tr><th>Level</th><th>Line</th><th>Check</th><th>What</th></tr></thead><tbody>' + rows + '</tbody></table>'; | |
| } | |
| var PEKKOREPORT = { escapeHtml: escapeHtml, summaryLine: summaryLine, toText: toText, toHtml: toHtml }; | |
| if (typeof module !== 'undefined' && module.exports) module.exports = PEKKOREPORT; | |
| else window.PEKKOREPORT = PEKKOREPORT; | |
| </script> | |
| <script> | |
| (function(){ | |
| var src=document.getElementById('src'), out=document.getElementById('out'), go=document.getElementById('go'), today=document.getElementById('today'); | |
| today.value=new Date().toISOString().slice(0,10); | |
| function run(){ try { var res=window.PEKKOENGINE.engine.check(src.value,{today:today.value}); out.innerHTML=window.PEKKOREPORT.toHtml(res); } catch(e){ out.innerHTML='<p class="sev error">Could not run: '+String(e.message||e)+'</p>'; } } | |
| go.onclick=run; if (src.value.trim()) run(); | |
| })(); | |
| </script> | |
| <section data-yj-install="free" style="margin:2rem auto 1rem;max-width:46rem;padding:1.25rem 1.25rem;border:1px solid #cfe3d6;border-radius:12px;background:#f6fbf8;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .4rem;font-size:1.2rem">Install free</h2><p style="margin:0 0 .8rem;color:#41505f">Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.</p><a href="https://open-vsx.org/extension/readystack/pekko-migration-gate" rel="noopener" data-yj-install-door="ovsx" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'pekko-migration-gate',src:'ovsx',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Open VSX (Cursor, VSCodium)</a><a href="https://www.npmjs.com/package/@readystack/pekko-migration-gate" rel="noopener" data-yj-install-door="npm" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'pekko-migration-gate',src:'npm',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">npm</a><a href="https://hub.docker.com/r/getreadystack/pekko-migration-gate" rel="noopener" data-yj-install-door="docker" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'pekko-migration-gate',src:'docker',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Docker Hub</a><pre style="margin:.5rem 0 0;padding:.6rem .8rem;background:#f3f5f8;border-radius:8px;font-size:.9rem;overflow:auto">npx @readystack/pekko-migration-gate <file> | |
| docker run --rm -v "$PWD:/w" getreadystack/pekko-migration-gate /w</pre><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://getreadystack.com/api/buy/cl/polar_cl_l6iN1uWt0FwWu7tBsczD0jWpP2vxFM54Wdwqb3KPi1G" rel="nofollow" style="color:#0f7b3f;text-decoration:underline">Team? One key for every ReadyStack linter, 5 seats, $149 once</a></p></section> | |
| <section data-yj-alert="rule" style="margin:1rem auto 1.5rem;max-width:46rem;padding:1.1rem 1.25rem;border:1px solid #d9dee6;border-radius:12px;background:#fbfcfd;font:15px/1.55 system-ui,-apple-system,Segoe UI,sans-serif"><b style="font-size:1.05rem">Get the full rule table as a PDF</b><div style="opacity:.78;margin:.35rem 0 .8rem">All 9 rules Pekko Migration Gate — Akka BSL licence check checks, each with its source and date, on printable pages you can hand to your team or auditor. We email it now, and once more only if a rule changes. No newsletter.</div><div style="display:flex;gap:8px;flex-wrap:wrap"><input id="yjae" type="email" placeholder="you@example.com" style="flex:1;min-width:210px;padding:11px 13px;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:#fff;color:inherit"><button id="yjab" style="padding:11px 18px;border-radius:8px;border:0;cursor:pointer;background:#0f7b3f;color:#fff;font:600 15px system-ui,sans-serif">Email me the PDF</button></div><div id="yjao" hidden style="margin-top:.6rem;color:#0f7b3f">Sent. It arrives within the hour - check spam too.</div><script>(function(){var b=document.getElementById("yjab"),e=document.getElementById("yjae");if(!b||!e)return;b.addEventListener("click",function(){var v=e.value.trim();if(!/.+@.+\..+/.test(v))return;try{localStorage.setItem("yj_em","1");}catch(_){}fetch(location.origin+"/api/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:v,slug:"pekko-migration-gate",lang:"en",source:"rule_table"+((b.closest&&b.closest("section")&&b.closest("section").getAttribute("data-yj-moved"))?"_at_result":"")})}).then(function(r){var o=document.getElementById("yjao");o.hidden=false;if(!r.ok){o.textContent="Could not save - please try again.";}}).catch(function(){var o=document.getElementById("yjao");o.hidden=false;o.textContent="Could not save - please try again.";});});})();</script><script>(function(){var e=document.getElementById("yjae"),s=e&&e.closest?e.closest("section"):null,o=document.getElementById("out");if(!s||!o)return;var d=false;function mv(ev){if(d)return;if(ev&&ev.target&&s.contains(ev.target))return;d=true;var b=o;while(b.parentNode&&b.parentNode!==document.body&&b.parentNode.tagName!=="MAIN"&&b.parentNode.tagName!=="ARTICLE")b=b.parentNode;if(!b.parentNode||b===s||b.contains(s))return;try{b.parentNode.insertBefore(s,b.nextSibling);s.setAttribute("data-yj-moved","1");}catch(_){}}document.addEventListener("input",mv,true);document.addEventListener("change",mv,true);})();</script></section> | |
| <section data-yj-cta="paid" style="margin:3rem auto;max-width:46rem;padding:1.5rem 1.25rem;border:1px solid #d8dee9;border-radius:12px;background:#fbfcfe;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .5rem;font-size:1.25rem">Get the complete version <span class="yj-price">$29</span></h2><p style="margin:.25rem 0 1rem;color:#41505f">This page is the working piece. The full pack has everything below.</p><p style="margin:0 0 1rem;color:#41505f">Pekko migration check: Akka 2.9.x is BSL 1.1 until at least 2026-10-23, Akka 2.8.8 until 2027-10-28 — each Akka release has its own Change Date.</p><p style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">Akka subscriptions start at $0.25 per core hour (Akka BSL FAQ). Eight production cores all year = 8 × 8,760 h × $0.25 = $17,520.</p><a href="https://getreadystack.com/api/buy/cl/polar_cl_31Zz7p4BZ19GYaxA6IFbSWHcVy77keudb2iZg2eBMSt" rel="nofollow" style="display:inline-block;padding:.7rem 1.3rem;border-radius:8px;background:#1b64f2;color:#fff;text-decoration:none;font-weight:600">Buy the full version — $29</a></section> | |
| <!--yj-share-s101--><div style="margin:28px 0 8px;text-align:center"><button id="yjcp" type="button" style="font:inherit;padding:10px 18px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Copy link</button><button id="yjimg" type="button" style="font:inherit;padding:10px 18px;margin-left:8px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Save result as image</button></div><script>(function(){var b=document.getElementById("yjimg");if(!b)return;b.addEventListener("click",function(){var o=document.getElementById("out");var txt=(o&&(o.innerText||o.textContent)||"").trim();if(!txt){b.textContent="(no result yet)";setTimeout(function(){b.textContent="Save result as image";},1500);return;}var lines=txt.split(String.fromCharCode(10)).filter(function(x){return x.trim();}).slice(0,10);var W=1200,P=56,c=document.createElement("canvas");c.width=W;var lh=38,H=P*2+70+lines.length*lh+60;c.height=H;var x=c.getContext("2d");x.fillStyle="#1a1512";x.fillRect(0,0,W,H);x.fillStyle="#f3e9d2";x.font="600 34px system-ui,Segoe UI,Arial";var t=(document.title||"").split("|")[0].trim();x.fillText(t.slice(0,54),P,P+34);x.font="22px ui-monospace,Menlo,Consolas,monospace";x.fillStyle="#e8dcc4";for(var i=0;i<lines.length;i++){x.fillText(lines[i].slice(0,88),P,P+70+i*lh+22);}x.font="600 22px system-ui,Segoe UI,Arial";x.fillStyle="#c9a227";var d=location.hostname.replace("www.","");x.fillText(d,W-P-x.measureText(d).width,H-P+6);c.toBlob(function(bl){var u=URL.createObjectURL(bl),a=document.createElement("a");a.href=u;a.download=(t||"result").replace(/[^a-z0-9]+/gi,"-").toLowerCase()+"-"+d+".png";document.body.appendChild(a);a.click();setTimeout(function(){URL.revokeObjectURL(u);a.remove();},2000);},"image/png");});})();</script><script>(function(){var b=document.getElementById("yjcp");if(!b)return;var t=b.textContent;b.addEventListener("click",function(){var u=location.href.split("#")[0];function d(){b.textContent="Link copied";setTimeout(function(){b.textContent=t;},1800);}if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(u).then(d,function(){prompt("",u);});}else{prompt("",u);}});})();</script> | |
| <script data-yj="yj-view-beacon">(function(){try{var p=location.pathname;var k='yjv:'+p;if(sessionStorage.getItem(k))return;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",ref:(document.referrer||''),src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}catch(e){}})();</script> | |
| <script data-yj="yj-use-beacon">(function(){try{var o=document.getElementById('out');if(!o)return;var p=location.pathname,k='yju:'+p,sent=false;function fire(){if(sent||sessionStorage.getItem(k))return;if(!(o.textContent||'').replace(/\s+/g,'').length)return;sent=true;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",t:'use',src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}var mo=new MutationObserver(function(){fire();if(sent)mo.disconnect();});mo.observe(o,{childList:true,characterData:true,subtree:true});}catch(e){}})();</script><div class="yj-home-find"><div class="yj-lgbar"><a href="/" class="yj-lg on">EN</a><a href="/de/" class="yj-lg">DE</a><a href="/ja/" class="yj-lg">JA</a><a href="/es/" class="yj-lg">ES</a><a href="/pt/" class="yj-lg">PT</a></div><section class="yj-find"><h2>Find a tool</h2><input id="yjq" type="search" autocomplete="off" placeholder="Type a product name, format or task"><div id="yjr"></div></section><style>.yj-lgbar{position:absolute;top:14px;right:18px;display:flex;gap:6px;z-index:60}.yj-lg{font:600 12px/1 system-ui,sans-serif;padding:6px 9px;border-radius:4px;text-decoration:none;color:#8b96a3;border:1px solid rgba(140,150,165,.28)}.yj-lg:hover{color:#e8eaed;border-color:rgba(160,175,195,.6)}.yj-lg.on{color:#0e1116;background:#cfd6de;border-color:#cfd6de}.yj-find{max-width:760px;margin:34px auto 8px;padding:0 20px}.yj-find h2{font:600 20px/1.3 system-ui,sans-serif;margin:0 0 10px}#yjq{width:100%;box-sizing:border-box;padding:13px 15px;font:400 15.5px system-ui,sans-serif;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:rgba(255,255,255,.04);color:inherit}#yjq:focus{outline:none;border-color:#7FD1C4}#yjr{margin-top:10px;display:flex;flex-direction:column;gap:6px}#yjr a{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;border:1px solid rgba(140,150,165,.22);border-radius:6px;text-decoration:none;font:400 14.5px/1.4 system-ui,sans-serif;color:inherit}#yjr a:hover{border-color:#7FD1C4}#yjr .pr{font:600 13px system-ui,sans-serif;color:#5fbf9a;white-space:nowrap}</style><script>(function(){var q=document.getElementById("yjq"),r=document.getElementById("yjr"),D=null;function load(){if(D)return Promise.resolve(D);return fetch("/search-index.json").then(function(x){return x.json();}).then(function(j){D=j;return j;}).catch(function(){D=[];return D;});}function esc(t){return String(t).replace(/[&<>"]/g,function(c){return {"&":"&","<":"<",">":">",'"':"""}[c];});}function run(){var v=q.value.trim().toLowerCase();if(v.length<2){r.innerHTML="";return;}load().then(function(j){var w=v.split(/\s+/),o=[];for(var i=0;i<j.length&&o.length<12;i++){var t=j[i].t.toLowerCase();var ok=true;for(var k=0;k<w.length;k++){if(t.indexOf(w[k])<0){ok=false;break;}}if(ok)o.push(j[i]);}r.innerHTML=o.length?o.map(function(x){return "<a href=\""+esc(x.u)+"\">"+"<span>"+esc(x.t)+"</span>"+(x.p?"<span class=\"pr\">$"+x.p+"</span>":"")+"</a>";}).join(""):"";});}q.addEventListener("input",run);q.addEventListener("focus",load);})();</script></div><section data-yj="yj-facts-v1" style="max-width:920px;margin:48px auto 0;padding:0 20px;font-family:system-ui,sans-serif"><style>.yj-article p{font:400 15.5px/1.7 system-ui,sans-serif;color:#26313b;margin:0 0 12px;max-width:72ch}.yj-article h2,.yj-article h3,.yj-article h4{font:600 17px/1.35 system-ui,sans-serif;color:#1b1f24;margin:22px 0 8px}.yj-article table{border-collapse:collapse;margin:10px 0 16px;font:14px/1.45 system-ui,sans-serif}.yj-article th,.yj-article td{border:1px solid #e2e6ea;padding:6px 10px;text-align:left}.yj-article th{background:#f4f6f8}.yj-article pre{background:#0f1720;color:#e6edf3;padding:12px 14px;border-radius:8px;overflow:auto;font:13px/1.5 ui-monospace,Menlo,monospace}.yj-article code{font:13px ui-monospace,Menlo,monospace;background:#f1f3f5;padding:1px 4px;border-radius:3px}.yj-article pre code{background:none;padding:0}.yj-article ul,.yj-article ol{font:15px/1.6 system-ui,sans-serif;color:#26313b}</style><p style="font:400 13px/1.5 system-ui,sans-serif;color:#6b7680;margin:0 0 14px"><time datetime="2026-09-28">Updated 2026-09-28</time> · ReadyStack</p><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","dateModified":"2026-09-28","author":{"@type":"Organization","name":"ReadyStack"}}</script><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Worked example</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 16px;color:#5b6570">Real numbers from this tool, line by line.</p><div class="yj-article"><p><img src="https://getreadystack.com/img/promo/sku353589_result_card.jpg" alt="Migrate from Akka to Pekko: the licence date is per release, not per version line" loading="lazy" style="max-width:100%;border-radius:6px"></p> | |
| <p>Six lines in a half-migrated build.sbt still ship Akka under the Business Source License, and the first two, akka-actor-typed and akka-stream at 2.9.3, stay licensed until at least 23 October 2026. That is what the free Pekko migration check reported for a Scala team's order-service build, measured on the sample file below.</p> | |
| <p>Lightbend moved Akka from Apache 2.0 to BSL 1.1 with Akka 22.10 (Akka core 2.7.0), released in October 2022. Production use of those releases at companies above $25 million annual revenue needs a commercial Akka licence. Akka's BSL FAQ says subscriptions start at $0.25 per core hour: eight production cores running all year come to 8 × 8,760 hours × $0.25 = $17,520.</p> | |
| <h3>The date that chatbots get wrong</h3> | |
| <p>Each BSL release converts to Apache 2.0 on its own Change Date, printed in that release's LICENSE file. From the tags in github.com/akka/akka:</p> | |
| <ul><li>Akka 2.8.0: 2026-03-16</li><li>Akka 2.8.8: 2027-10-28</li><li>Akka 2.9.0: 2026-10-23</li><li>Akka 2.9.5: 2027-08-19</li><li>Akka 2.10.0: 2027-10-16</li><li>Akka 2.7.x: "TBD (3 years after 2.7.0 release)"</li></ul> | |
| <p>"Akka 2.8 is Apache now" is true for 2.8.0 and false for 2.8.8. The later patch you upgraded to for a bug fix restarted the clock.</p> | |
| <h3>What the check found in the sample build.sbt</h3> | |
| <pre><code>val AkkaVersion = "2.9.3" | |
| val AkkaHttpVersion = "10.5.3" | |
| "com.typesafe.akka" %% "akka-actor-typed" % AkkaVersion, | |
| "com.typesafe.akka" %% "akka-stream" % AkkaVersion, | |
| "com.typesafe.akka" %% "akka-http" % AkkaHttpVersion, | |
| "com.lightbend.akka" %% "akka-stream-alpakka-s3" % "6.0.2", | |
| "com.typesafe.akka" %% "akka-stream-kafka" % "4.0.2", | |
| "org.apache.pekko" %% "pekko-connectors-csv" % "1.0.2",</code></pre> | |
| <ul><li>akka-actor-typed 2.9.3 → pekko-actor-typed 1.x (error: BSL until at least 2026-10-23)</li><li>akka-stream 2.9.3 → pekko-stream 1.x (error)</li><li>akka-http 10.5.3 → pekko-http 1.x (warning: Akka HTTP is BSL from 10.4.0)</li><li>akka-stream-alpakka-s3 6.0.2 → pekko-connectors-s3 1.x (warning: Alpakka is BSL from 5.0.0)</li><li>akka-stream-kafka 4.0.2 → pekko-connectors-kafka 1.x (warning: Alpakka Kafka is BSL from 4.0.0)</li><li>pekko-connectors-csv next to Akka → drop every com.typesafe.akka line (error: half-migrated build)</li></ul> | |
| <p>The migrated build, with every coordinate on org.apache.pekko, gives 0 findings.</p> | |
| <h3>The config that Pekko silently ignores</h3> | |
| <p>Swapping jars is half the move. Pekko reads settings only from the pekko.* namespace, so an <code>akka { actor.provider = cluster }</code> block is ignored and the node starts with defaults. A default Pekko node accepts only pekko:// addresses, so akka:// seed nodes are refused unless you set <code>pekko.remote.accept-protocol-names = ["akka", "pekko"]</code> for the rolling switchover. The default ports differ too: Akka uses 25520 (Artery) and 2552 (classic), Pekko uses 17355 and 7355. The checker flags each of these lines, plus <code>import akka.</code> in Scala and Java sources.</p> | |
| <h3>How to run it</h3> | |
| <p>Open build.sbt, pom.xml, build.gradle or application.conf in VS Code with the extension installed, or paste the file into the free web page and set the check date. Nine rules run on the file and every finding prints the Pekko line to use. Change the date to 2026-10-24 and Akka 2.9.0 moves from error to converted, while 2.9.3 stays flagged because its own date is later.</p> | |
| <p>Pekko 1.x forked from Akka 2.6.x, so code that uses APIs added in Akka 2.7 or later may need rework after the swap.</p></div><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:30px 0 10px;color:#1b1f24">15 seconds — what it actually does</h2><video controls muted playsinline preload="none" poster="/img/promo/sku353589_result_card.jpg" style="width:100%;max-width:360px;border-radius:10px;display:block;margin:0 auto"><source src="/media/sku353589_short.mp4" type="video/mp4"></video><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:34px 0 6px;color:#1b1f24">Questions people ask</h2><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does Pekko Migration Gate check?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads build.sbt, pom.xml, build.gradle and application.conf files and flags every Akka artifact still under the Business Source License 1.1 on the date you choose, using the Change Date printed in each Akka release's LICENSE. It also flags akka.* config keys, akka:// seed addresses, Akka default ports and akka imports that Apache Pekko ignores, and prints the Pekko line to use.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Who is the Pekko migration check for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Scala and Java teams running Akka 2.7 or later in production at companies above $25 million annual revenue, where the BSL requires a commercial Akka licence, and platform engineers moving those services to Apache Pekko. It also helps the person who owns software licences find out which exact Akka versions a build still ships.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why not just ask a chatbot whether my Akka version is still BSL?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">The Change Date is set per release, not per minor line. Akka 2.8.0 turned Apache 2.0 on 2026-03-16, but Akka 2.8.8 stays BSL until 2027-10-28 and Akka 2.9.0 until 2026-10-23. A general answer such as 'Akka 2.8 is Apache now' is wrong for most 2.8 builds. The checker compares each resolved version with its own date.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What is free and what does the full version add?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free: the open file is checked completely, every finding with its reason and the Pekko replacement line, in VS Code and on the web page, with no key. The full version, $29 once, sweeps every build file and config in the repository into one Markdown migration report you can hand to the person who owns the Akka licence.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does staying on licensed Akka cost?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Akka's BSL FAQ says Akka subscriptions start at $0.25 per core hour. Eight production cores running all year come to 8 × 8,760 hours × $0.25 = $17,520 a year. Apache Pekko is Apache 2.0 licensed and has no such fee; the checker lists the dependency, config and import lines that must change before you can drop Akka.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why not just ask ChatGPT or another AI chat?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. Pekko Migration Gate — Akka BSL licence check checks the file you open against 9 rules from a rule set dated 2026-09-28, and points at the exact line with the fix. For a filing, an audit or a client you need that dated result on your own files.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does Pekko Migration Gate check?", "acceptedAnswer": {"@type": "Answer", "text": "It reads build.sbt, pom.xml, build.gradle and application.conf files and flags every Akka artifact still under the Business Source License 1.1 on the date you choose, using the Change Date printed in each Akka release's LICENSE. It also flags akka.* config keys, akka:// seed addresses, Akka default ports and akka imports that Apache Pekko ignores, and prints the Pekko line to use."}}, {"@type": "Question", "name": "Who is the Pekko migration check for?", "acceptedAnswer": {"@type": "Answer", "text": "Scala and Java teams running Akka 2.7 or later in production at companies above $25 million annual revenue, where the BSL requires a commercial Akka licence, and platform engineers moving those services to Apache Pekko. It also helps the person who owns software licences find out which exact Akka versions a build still ships."}}, {"@type": "Question", "name": "Why not just ask a chatbot whether my Akka version is still BSL?", "acceptedAnswer": {"@type": "Answer", "text": "The Change Date is set per release, not per minor line. Akka 2.8.0 turned Apache 2.0 on 2026-03-16, but Akka 2.8.8 stays BSL until 2027-10-28 and Akka 2.9.0 until 2026-10-23. A general answer such as 'Akka 2.8 is Apache now' is wrong for most 2.8 builds. The checker compares each resolved version with its own date."}}, {"@type": "Question", "name": "What is free and what does the full version add?", "acceptedAnswer": {"@type": "Answer", "text": "Free: the open file is checked completely, every finding with its reason and the Pekko replacement line, in VS Code and on the web page, with no key. The full version, $29 once, sweeps every build file and config in the repository into one Markdown migration report you can hand to the person who owns the Akka licence."}}, {"@type": "Question", "name": "What does staying on licensed Akka cost?", "acceptedAnswer": {"@type": "Answer", "text": "Akka's BSL FAQ says Akka subscriptions start at $0.25 per core hour. Eight production cores running all year come to 8 × 8,760 hours × $0.25 = $17,520 a year. Apache Pekko is Apache 2.0 licensed and has no such fee; the checker lists the dependency, config and import lines that must change before you can drop Akka."}}, {"@type": "Question", "name": "Why not just ask ChatGPT or another AI chat?", "acceptedAnswer": {"@type": "Answer", "text": "A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. Pekko Migration Gate — Akka BSL licence check checks the file you open against 9 rules from a rule set dated 2026-09-28, and points at the exact line with the fix. For a filing, an audit or a client you need that dated result on your own files."}}]}</script><div id="yj-ask" style="margin:36px 0 0;padding:18px 18px 16px;border:1px solid #e2e6ea;border-radius:10px;background:#fbfbfc"><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:0 0 4px;color:#1b1f24">Ask about this tool</h2><p style="font:400 13.5px/1.5 system-ui,sans-serif;margin:0 0 12px;color:#5b6570">One question, answered by the person who built it. Your email only if you want the answer sent.</p><form onsubmit="return yjAsk(event)" style="display:grid;gap:8px"><textarea name="question" required minlength="10" maxlength="2000" rows="3" placeholder="Your question" style="font:14px/1.5 system-ui,sans-serif;padding:10px;border:1px solid #cfd6dd;border-radius:6px"></textarea><div style="display:flex;gap:8px;flex-wrap:wrap"><input type="email" name="email" placeholder="Email (optional)" style="flex:1;min-width:200px;font:14px system-ui,sans-serif;padding:9px 10px;border:1px solid #cfd6dd;border-radius:6px"><button type="submit" style="font:600 14px system-ui,sans-serif;padding:9px 18px;border:0;border-radius:6px;background:#1b1f24;color:#fff;cursor:pointer">Send</button></div><p id="yj-ask-msg" style="font:13px system-ui,sans-serif;margin:2px 0 0;color:#0a6238;min-height:1em"></p></form><script>function yjAsk(e){e.preventDefault();var f=e.target,m=document.getElementById("yj-ask-msg");m.style.color="#0a6238";fetch(location.origin+"/api/ask",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sku:353589,slug:"pekko-migration-gate",lang:"en",question:f.question.value,email:f.email.value,page:location.pathname})}).then(function(r){if(!r.ok)throw 0;m.textContent="Thanks \u2014 noted. Answers land on this page and, if you left an email, in your inbox.";f.question.value="";}).catch(function(){m.style.color="#a8551f";m.textContent="Could not send. Please try again in a minute.";});return false;}</script></div></section><section class="yj-related" style="max-width:920px;margin:56px auto 40px;padding:0 20px"><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Same job, next tool</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 20px;color:#5b6570">Free in the browser. The full version is a one-time licence.</p><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px"><a class="yj-rel-c" href="https://getreadystack.com/tools/firmware-release-gate"><span class="yj-rel-t">Firmware Release Gate for sdkconfig and prj.conf</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/renpy-release-gate"><span class="yj-rel-t">Ren'Py Release Gate</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/pyproject-release-gate"><span class="yj-rel-t">pyproject.toml Release Gate (PEP 639)</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/huggingface-model-license-matrix"><span class="yj-rel-t">Hugging Face Model Licence Matrix — all 70 model-card `license:` identifiers ×</span><span class="yj-rel-p">$4.99</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/dotnet-eol-support-gate"><span class="yj-rel-t">.NET EOL & CRA Support Window Gate</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/age-gate-lint"><span class="yj-rel-t">Age Gate Lint — UK Online Safety Act</span><span class="yj-rel-p">$29</span></a></div><style>.yj-rel-c{display:flex;flex-direction:column;gap:8px;padding:15px 16px;border:1px solid #e2e6ea;border-radius:6px;text-decoration:none;background:#fff}.yj-rel-c:hover{border-color:#b9c2cb;background:#fafbfc}.yj-rel-t{font:500 14.5px/1.42 system-ui,sans-serif;color:#1b1f24}.yj-rel-p{font:600 13px system-ui,sans-serif;color:#0a6238}</style></section></body> | |
| </html> | |