Migration diagram

Read this page in the documentation

Migration diagram What a migration does to a table, drawn as the before and after. The code What it produces Generated by running the snippet above — this is the generator's real output, rebuilt by scripts/build-diagram-examples.mjs, not a picture of it. <div class="diagram-example"> <!-- Generated by ts-prorm-orm MigrationDiagram --> <svg xmlns="http://www.w3.org/2000/svg" width="500" height="540" viewBox="0 0 500 540"><rect width="500" height="540" fill="#ffffff"/><rect width="500" height="80" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><g transform="translate(30, 24)"><ellipse cx="14" cy="8" rx="12" ry="4" fill="none" stroke="#000000" stroke-width="1"/><path d="M2 12v12c0 2.2 5.4 4 12 4s12-1.8 12-4V12" fill="none" stroke="#000000" stroke-width="1"/><path d="M2 16c0 2.2 5.4 4 12 4s12-1.8 12-4" fill="none" stroke="#000000" stroke-width="1"/></g><text x="58" y="36" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="22" font-weight="bold" fill="#000000">Add author to posts</text><text x="58" y="54" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="12" fill="#666666">Link every post to the user who wrote it</text><text x="470" y="54" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="11" fill="#666666" text-anchor="end">2026-01-12</text><rect x="370" y="20" width="100" height="26" fill="#ffffff" stroke="#000000" stroke-width="1"/><text x="420" y="38" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="11" font-weight="bold" fill="#000000" text-anchor="middle">MIGRATION</text><rect x="40" y="120" width="320" height="154" fill="#ffffff" stroke="#000000" stroke-width="1"/><rect x="40" y="120" width="320" height="42" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><rect x="52" y="130" width="56" height="22" fill="#ffffff" stroke="#000000" stroke-width="1"/><text x="80" y="145" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="9" font-weight="bold" fill="#000000" text-anchor="middle">MOD</text><text x="120" y="147" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="14" font-weight="bold" fill="#000000">posts</text><rect x="40" y="162" width="320" height="28" fill="#ffffff"/><rect x="40" y="162" width="4" height="28" fill="#000000"/><circle cx="56" cy="176" r="6" fill="#ffffff" stroke="#000000" stroke-width="1"/><path d="M53 176h6M56 173v6" stroke="#000000" stroke-width="1" fill="none"/><text x="76" y="180" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="12" font-weight="bold" fill="#000000">authorId</text><rect x="298" y="168" width="54" height="16" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="325" y="180" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" font-weight="bold" fill="#000000" text-anchor="middle">INTEGER</text><line x1="40" y1="190" x2="360" y2="190" stroke="#000000" stroke-width="1"/><rect x="40" y="190" width="320" height="28" fill="#f0f0f0"/><rect x="40" y="190" width="4" height="28" fill="#000000"/><circle cx="56" cy="204" r="6" fill="#ffffff" stroke="#000000" stroke-width="1"/><path d="M53 204h6" stroke="#000000" stroke-width="1" fill="none"/><path d="M56 201v6" stroke="#000000" stroke-width="1" fill="none"/><text x="76" y="208" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="12" font-weight="bold" fill="#000000">title</text><text x="350" y="208" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" fill="#666666" text-anchor="end">VARCHAR(120) -&gt; VARCHAR(200)</text><line x1="40" y1="218" x2="360" y2="218" stroke="#000000" stroke-width="1"/><rect x="40" y="218" width="320" height="28" fill="#ffffff"/><rect x="40" y="218" width="4" height="28" fill="#000000"/><circle cx="56" cy="232" r="6" fill="#ffffff" stroke="#000000" stroke-width="1"/><path d="M53 232h6" stroke="#000000" stroke-width="1" fill="none"/><text x="76" y="236" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="12" font-weight="bold" fill="#000000">legacyauthor</text><rect x="268" y="224" width="84" height="16" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="310" y="236" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" font-weight="bold" fill="#000000" text-anchor="middle">VARCHAR(100)</text><line x1="40" y1="246" x2="360" y2="246" stroke="#000000" stroke-width="1"/><rect x="40" y="246" width="320" height="28" fill="#f0f0f0"/><text x="52" y="264" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="9" font-weight="bold" fill="#000000">3 changes</text><rect x="40" y="324" width="320" height="126" fill="#ffffff" stroke="#000000" stroke-width="1"/><rect x="40" y="324" width="320" height="42" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><rect x="52" y="334" width="56" height="22" fill="#ffffff" stroke="#000000" stroke-width="1"/><text x="80" y="349" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="9" font-weight="bold" fill="#000000" text-anchor="middle">ADD</text><text x="120" y="351" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="14" font-weight="bold" fill="#000000">posttags</text><rect x="40" y="366" width="320" height="28" fill="#ffffff"/><rect x="40" y="366" width="4" height="28" fill="#000000"/><circle cx="56" cy="380" r="6" fill="#ffffff" stroke="#000000" stroke-width="1"/><path d="M53 380h6M56 377v6" stroke="#000000" stroke-width="1" fill="none"/><text x="76" y="384" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="12" font-weight="bold" fill="#000000">postId</text><rect x="298" y="372" width="54" height="16" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="325" y="384" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" font-weight="bold" fill="#000000" text-anchor="middle">INTEGER</text><line x1="40" y1="394" x2="360" y2="394" stroke="#000000" stroke-width="1"/><rect x="40" y="394" width="320" height="28" fill="#f0f0f0"/><rect x="40" y="394" width="4" height="28" fill="#000000"/><circle cx="56" cy="408" r="6" fill="#ffffff" stroke="#000000" stroke-width="1"/><path d="M53 408h6M56 405v6" stroke="#000000" stroke-width="1" fill="none"/><text x="76" y="412" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="12" font-weight="bold" fill="#000000">tagId</text><rect x="298" y="400" width="54" height="16" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><text x="325" y="412" font-family="ui-monospace, SFMono-Regular, Menlo, Consolas, monospace" font-size="8" font-weight="bold" fill="#000000" text-anchor="middle">INTEGER</text><line x1="40" y1="422" x2="360" y2="422" stroke="#000000" stroke-width="1"/><rect x="40" y="422" width="320" height="28" fill="#f0f0f0"/><text x="52" y="440" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="9" font-weight="bold" fill="#000000">2 changes</text><rect x="40" y="490" width="90" height="28" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><circle cx="56" cy="504" r="6" fill="#ffffff" stroke="#000000" stroke-width="1"/><text x="70" y="508" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="11" font-weight="bold" fill="#000000">Added</text><rect x="150" y="490" width="90" height="28" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><circle cx="166" cy="504" r="6" fill="#ffffff" stroke="#000000" stroke-width="1"/><text x="180" y="508" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="11" font-weight="bold" fill="#000000">Removed</text><rect x="260" y="490" width="90" height="28" fill="#f0f0f0" stroke="#000000" stroke-width="1"/><circle cx="276" cy="504" r="6" fill="#ffffff" stroke="#000000" stroke-width="1"/><text x="290" y="508" font-family="ui-sans-serif, -apple-system, Segoe UI, Helvetica, Arial, sans-serif" font-size="11" font-weight="bold" fill="#000000">Modified</text></svg> </div> It takes the change set, not a model — changes[] of tables, each with the columns added, modified or removed. A modify shows the transition, VARCHAR(120) -> VARCHAR(200), which is the part a reviewer actually needs to see. Saving it generate() returns the SVG as a string; save(path) writes it straight to disk. Related reading Diagram generators — every generator and its options Models — the definitions these are drawn from