Back to blog

Blog

Reverse Engineer Architecture From Code: A Repo Playbook

How to reverse engineer architecture from code: a six-step repo playbook with real commands, a worked example and a checklist for what code cannot tell you.

reverse engineer architecture from codeUpdated 11/4/2026Shafi Khan

Reverse Engineer Architecture From Code: A Repo Playbook

How to reverse engineer architecture from code, the short version: work from the outside in. List what gets deployed from the infrastructure files, trace external calls from config, map internal dependencies with a graph tool, find the hotspots in git history, then validate everything against runtime traces and the humans on call. Code gives you structure. It won't give you intent.

You just inherited a repo. The README says "see the wiki." The wiki has a diagram from 2023 with a box labelled "Legacy Service (TBD)." The person who drew it left. Your first ticket touches payments, and nobody can say what else that will break.

No shame in it, this is most repos. The good news: you can rebuild a usable picture in an afternoon if you collect evidence in the right order, instead of reading files alphabetically and hoping for enlightenment.

Why reverse engineering architecture from code needs a method

Code is one witness, and it's a partial one. Each source of evidence answers a different question, and each one has a blind spot. Pretend otherwise and you'll ship a confident diagram that's confidently wrong.

EvidenceWhat it provesWhat it can't prove
Compose, Kubernetes and Terraform filesWhat is meant to be deployedWhether it is what's actually running
Environment variables and SDK clientsWhich external systems are reachableWhether they get called, or how often
Import and module graphsHow code is structuredRuntime paths through dynamic dispatch or message queues
SQL migrations and DDLThe data model over timeWhich service really owns each table
Git historyWhere change and risk concentrateWhy the code ended up this way
Traces and logsWhat really happens in productionRare paths that didn't fire in your window

So the job isn't "generate a diagram." It's cross-examining witnesses until the story holds up. Tag each box and arrow with where it came from, and you can tell facts from guesses at a glance.

→ Bring repository insight into your architecture review with Code Analysis

How to reverse engineer architecture from code in 6 steps

Step 1: Pick the question first

"Document the whole system" is how you lose a month. Pick a real question: "What breaks if we replace the payments provider?" or "Can this service move to another region?" Scope decides what you can safely ignore.

Step 2: Find what gets deployed

Skip the application code for now. Start with the files that name the deployable units:

git ls-files | grep -E '(Dockerfile|compose.*\.ya?ml|\.tf$|Chart\.yaml|kustomization\.yaml)'

Every Dockerfile is a candidate deployable. Every Terraform file is a claim about infrastructure. In C4 terms, you're collecting containers, which means applications and data stores, not Docker containers. An S3 bucket counts. A SPA counts.

If the repo uses Terraform, get the dependency view for free:

terraform init
terraform graph | dot -Tsvg > graph.svg

By default, terraform graph shows only the dependency ordering of resources and prints DOT, so you'll need Graphviz. On anything big it turns into spaghetti fast. The Terraform module visualizer gives you a more readable view of modules, resources and outputs.

Step 3: Trace the edges out of the system

External dependencies hide in config, not imports. Grep for them:

grep -rEn 'https?://|_URL|_HOST|_ENDPOINT' \
  --include='*.env*' --include='*.y*ml' --include='*.tf' \
  --exclude-dir=node_modules .

Then find the ways in. Look for HTTP routes, queue consumers, scheduled jobs and webhooks:

grep -rEln '@(Get|Post)Mapping|@app\.(get|post|route)|router\.(get|post)|app\.(get|post)\(' \
  --exclude-dir=node_modules src

Adjust the pattern for your framework. You're after a list of entry points, not a perfect parse.

Step 4: Map the internal structure

Now you've earned the right to read code. Use a graph tool so you aren't holding the whole thing in your head. For JavaScript and TypeScript, dependency-cruiser does the job:

npx dependency-cruiser src --include-only "^src" --output-type dot \
  | dot -T svg > dependency-graph.svg

Most ecosystems have an equivalent. What you're looking for is cycles, god modules that everything imports, and places where a "shared" library is actually a hidden coupling between teams. That's where your service boundaries are really drawn, whatever the org chart says.

One trap: the GitHub dependency graph isn't this. It summarizes manifest and lock files, so it tells you about packages, licenses and known vulnerabilities. Useful, but it's a supply-chain inventory, not a map of your system.

Step 5: Find hotspots in the codebase

Git history shows where the bodies are buried. List the most-changed files from the last year:

git log --format=format: --name-only --since=12.month \
  | grep -v '^$' | sort | uniq -c | sort -nr | head -20

High churn plus high fan-in from Step 4 is your danger zone. Then see who actually knows that code:

git shortlog -sn --no-merges --since=12.month HEAD -- src/payments

Keep the HEAD. Without a revision, git shortlog reads from stdin when it's not attached to a terminal, so this one silently returns nothing inside a script.

Step 6: Validate against reality

Static analysis tells you what could happen. Runtime evidence tells you what does. If you have OpenTelemetry traces, follow one real request through them, since a trace shows the path a request takes through your services. No tracing? Use access logs, or just ask the on-call engineer. Twenty minutes with them beats two days of grep, and they'll tell you about the nightly job nobody committed.

→ Turn repository context into a system overview with CoDocs

Worked example: what a compose file gives away

Here's a small, made-up shop stack. It's the kind of file you'd find on day one:

services:
  web:
    build: ./web
    ports:
      - '8080:8080'
    environment:
      DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/shop
      REDIS_URL: redis://cache:6379
      BROKER_URL: amqp://queue:5672
    depends_on:
      - db
      - cache
      - queue
  worker:
    build: ./worker
    environment:
      DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/shop
      BROKER_URL: amqp://queue:5672
      PAYMENTS_API_URL: https://payments.example.com
    depends_on:
      - queue
  db:
    image: postgres:17
  cache:
    image: redis:7
  queue:
    image: rabbitmq:4

Run docker compose config first, because it resolves variables and merges overrides into the model Compose will really use. Then read it twice.

First pass, depends_on: web needs db, cache and queue. Worker needs queue. Tidy. Also incomplete, because depends_on only controls startup and shutdown order. It was never a call graph.

Second pass, environment: this is where the real story lives.

  • Worker also talks to db, which depends_on never mentioned. So web and worker share a database, and that's a coupling worth flagging.
  • Worker calls an external payments API. That's the most important dependency in the file, and it's one line of config. A diagram built from services: alone would never draw it.
  • Web publishes to the queue and worker consumes, probably. The direction isn't in this file. You need the code from Step 3 to confirm it.

Three findings in five minutes, and one is a real architecture smell. Start with a generated view of your own file, then annotate what it can't know. Got manifests or a schema dump instead? The Kubernetes YAML visualizer and SQL DDL to ER diagram tool do the same for those.

→ Map your compose file for free with the Docker Compose Diagrammer

Can you generate an architecture diagram from a GitHub repository?

Yes, with an asterisk. You can generate an accurate picture of what's in the repo. You can't generate what isn't in it, which includes console changes, the team next door's dependency on you, and the reason any of this exists.

ApproachGood forWatch out for
terraform graph and GraphvizFree, exact resource dependency orderingNoisy at scale, no application view
dependency-cruiser or similarInternal code structure and rule checksLanguage-specific; doesn't show infrastructure
GitHub dependency graphPackage inventory and vulnerability infoNot an architecture view
Diagram as codeVersioned diagrams beside the repoHand-written, so it can rot like any doc
Architecto Code AnalysisRepository graph, hotspot views and impact context in a design reviewVerify findings against runtime, like any static analysis

Our take: don't pick one. Generated graphs are excellent evidence and terrible communication. Nobody in a design review wants 400 nodes. The output you want is a small, opinionated diagram, backed by those graphs.

That's the gap Code Analysis targets. It connects your GitHub or GitLab repository through a Git-backed analysis surface, then gives you graph, pattern and hotspot views you can use to check what a change could affect downstream. If you need the write-up too, CoDocs builds technical documentation from repository context. And when you know the shape of the system, describe it to Architect AI for an editable architecture you can refine, rather than dragging boxes for a whole afternoon.

→ Connect a repository and inspect its structure with Code Analysis

C4 diagrams from existing code: what to actually produce

Stop at two diagrams, unless you've got a reason. The C4 model has four core levels, but its own guidance is that you don't need all of them, and that context and container diagrams are enough for most teams.

DiagramBuilt fromAudience
System contextSteps 1 and 3: users and external systemsEveryone, including non-engineers
ContainerSteps 2 and 3: apps, data stores, how they talkEngineers and reviewers
ComponentStep 4, for the area you're changingThe team doing the work

Mark every element as confirmed or inferred, because an unmarked guess is just fan fiction with icons. A dashed line for "seen in config, not in traces" is honest, and reviewers will trust the rest more because of it.

Then write down what the code refused to tell you. The decision logs explainer is a solid starting point, because a diagram without the "why" is how you end up back here in two years. Once it's agreed, keep the picture honest: Drift Detector compares environments and IaC context to show where intent and deployed reality have diverged.

→ Draft your container diagram from a plain-English description

Reverse engineering architecture checklist

Run this before you call the diagram done:

  • A single question defines the scope, and it's written on the diagram
  • Every Dockerfile, chart and Terraform root is accounted for
  • External systems from config appear as boxes, including SaaS and partner APIs
  • Entry points are listed: HTTP, queues, schedules and webhooks
  • Shared databases and shared libraries are flagged as coupling
  • Circular dependencies are noted, not hidden
  • Top hotspots are named, with a current owner beside each
  • At least one real request is traced end to end
  • Each arrow is marked confirmed or inferred
  • The on-call engineer has reviewed it and found the thing you missed
  • Open questions and unexplained decisions are written down

→ Turn this into a repeatable review with the Architecture Review Checklist Builder

Key takeaways

  • Work outside-in: deployables, then edges, then internals, then runtime.
  • Treat every source as a partial witness, and note where each box came from.
  • depends_on is startup order, and the GitHub dependency graph is a package list. Neither is your architecture.
  • Git churn plus fan-in shows you where the risk lives.
  • Generated graphs are evidence. The deliverable is a small diagram with a point of view.
  • Code never tells you why. Capture that before the last person who knows leaves.

→ Get code-aware context into your next design review

FAQ

How do you reverse engineer architecture from code?

Work from the outside in. List what gets deployed and what stores data from the infrastructure files, trace external calls from configuration, map internal module dependencies, find hotspots in git history, then validate the result against runtime traces and the people who run the system. Static code alone shows what could happen, not what does.

Can you generate an architecture diagram from a GitHub repository?

Partly. Dependency tools and repository analysis can produce an accurate graph of code structure, and infrastructure files can be turned into a topology view. A repository alone rarely shows live traffic, manual console changes or why a decision was made, so treat any generated diagram as a draft and validate it.

What is the fastest way to understand a new codebase?

Read the infrastructure files first, because they name the deployable units and data stores. Then find the entry points, follow one real request end to end, and check which files change most often. That gives you a working map before you read a single business rule in depth.

Does the GitHub dependency graph show my system architecture?

No. It summarizes the manifest and lock files in a repository, so it lists packages and their versions, licenses and known vulnerabilities. It doesn't describe how your own modules or services relate to each other, which is what an architecture diagram needs to show.

Which C4 diagrams should you produce from existing code?

Start with a system context diagram and a container diagram. The C4 model says those two are enough for most software development teams, and you don't need all four levels. Add a component diagram only for the area you're actively changing.

→ Generate technical documentation from your repository with CoDocs

Stop inheriting mystery systems

You can now reverse engineer architecture from code without reading every file: evidence first, small diagram second, validated by the people who get paged. The 2023 diagram finally gets to retire.

The slow part isn't drawing. It's collecting the evidence and keeping it attached to the design as the system moves. Connect your repo, get the structure in view, and take the argument to the design review instead of the wiki.

→ Start free and connect your first repository

FAQ

Questions readers ask before they act on this page.

How do you reverse engineer architecture from code?

Work from the outside in. List what gets deployed and what stores data from the infrastructure files, trace external calls from configuration, map internal module dependencies, find hotspots in git history, then validate the result against runtime traces and the people who run the system. Static code alone shows what could happen, not what does.

Can you generate an architecture diagram from a GitHub repository?

Partly. Dependency tools and repository analysis can produce an accurate graph of code structure, and infrastructure files can be turned into a topology view. A repository alone rarely shows live traffic, manual console changes or why a decision was made, so treat any generated diagram as a draft and validate it.

What is the fastest way to understand a new codebase?

Read the infrastructure files first, because they name the deployable units and data stores. Then find the entry points, follow one real request end to end, and check which files change most often. That gives you a working map before you read a single business rule in depth.

Does the GitHub dependency graph show my system architecture?

No. It summarizes the manifest and lock files in a repository, so it lists packages and their versions, licenses and known vulnerabilities. It doesn't describe how your own modules or services relate to each other, which is what an architecture diagram needs to show.

Which C4 diagrams should you produce from existing code?

Start with a system context diagram and a container diagram. The C4 model says those two are enough for most software development teams, and you don't need all four levels. Add a component diagram only for the area you're actively changing.

Related reading

Keep moving through the architecture workflow.

Free tool

Docker Compose Diagrammer

Quickly explain local platform topologies, integration stacks, and migration candidates by turning compose files into a visual dependency map.

docker compose visualizercompose file diagramcontainer topology mapper

Free tool

Terraform Module Visualizer

Map resources, providers, modules, and outputs from Terraform files into a readable dependency view for reviewers and platform engineers.

terraform graph viewerterraform module diagramiac visualizer

Free tool

Kubernetes YAML Visualizer

Read Deployments, Services, Ingresses, StatefulSets, and ConfigMaps as one system view instead of a folder full of YAML files.

kubernetes manifest visualizerk8s yaml diagramkubernetes topology tool

Free tool

SQL DDL to ER Diagram

Turn raw CREATE TABLE statements into an ER-style map with tables, relationships, field counts, and exportable Mermaid syntax.

ddl to erdsql schema visualizercreate table diagram generator

Guide

What decision logs means in System Design Reviews

What decision logs means in System Design Reviews with technical review guidance, practical artifacts, and a workflow path into diagrams, documentation, and architecture governance.

system design reviewdecision logsarchitecture review process

Guide

What documentation standards means in Infrastructure as Code

What documentation standards means in Infrastructure as Code with technical review guidance, practical artifacts, and a workflow path into diagrams, documentation, and architecture governance.

infrastructure as codedocumentation standardsterraform best practices

Comparison

Architecto vs CodeWiki (Gemini)

Architecto vs CodeWiki (Gemini) with a workflow-first comparison across diagrams, architecture review, technical documentation, and code-adjacent implementation evidence.

codewiki (gemini) alternativearchitecto vs codewiki (gemini)brand comparison
Reverse Engineer Architecture From Code: A Repo Playbook | Architecto