Frankenstein in Programming — What It Is, Causes and Prevention

Author: IT Sectr Published: 2026-07-26 Reading time: 10 min

Frankenstein in programming is code assembled from incompatible parts of different technologies, styles and architectures. According to ThoughtWorks Technology Radar research (2024), 28% of large projects show signs of Frankenstein syndrome — architectural eclecticism arising from the lack of a unified technical vision. By analogy with Mary Shelley's novel, such code works, but its maintenance turns into a nightmare.

Key Takeaways

  • Frankenstein is an antipattern where the system is assembled from heterogeneous, poorly compatible components
  • Main causes: lack of an architect, project mergers, “creativity without boundaries”
  • The problem — each component requires knowledge of its own technology, and interaction is unpredictable
  • Refactoring Frankenstein requires unifying the technology stack and establishing clear boundaries
  • Architecture Decision Records and RFCs are the best prevention tools

What Is Frankenstein in Programming

Frankenstein (Frankenstein code, Frankenstein pattern) is an antipattern where a software system is assembled from parts not designed to work together. Like Frankenstein's monster, such code can function, but it is ugly, unpredictable, and dangerous at the slightest changes.

The term comes from literature: in Mary Shelley's novel “Frankenstein, or The Modern Prometheus” (1818), a scientist created a living being from fragments of different dead people's bodies. In programming, the analogy is exact — developers take pieces of different frameworks, libraries, languages and glue them together “live”, producing a working but monstrous result.

The difference between Frankenstein and spaghetti code is in scale and nature. Spaghetti code is a tangled structure within one technology stack. Frankenstein is eclecticism at the architecture level: different technologies, incompatible paradigms, conflicting approaches within the same system.

Frankenstein vs Microservices

Microservice architecture allows using different technologies for different services, but with clear boundaries and standardized interaction protocols. Frankenstein is chaotic mixing without boundaries: REST and GraphQL in one controller, two ORMs in one module, SQL and NoSQL for one entity.

Why Does Frankenstein Syndrome Occur

Lack of a technical leader or architect is the root cause. When there is no person responsible for architectural integrity, each developer chooses tools “for themselves”. One likes Spring, another likes Guice, a third uses a custom DI. The result is an architectural mishmash.

Project merger is the second common cause. Two teams developed their modules independently, using different stacks. When the modules need to be combined into one application, they are simply “glued” together with adapters and middleware. The result is Frankenstein.

Corporate acquisitions are the third scenario. Company A bought Company B and wants to integrate its product into its own. Instead of rewriting — glueing through APIs, shared databases, and band-aids. After a year, the system becomes a monster that no one understands.

CausesDescriptionTypical Result
No architectEach developer chooses their own stack3 different HTTP clients in one module
Project mergerTwo products glued into oneTwo ORMs, two logging methods
M&AAcquisition of a company with its productHybrid of different architectures and styles
ExperimentsIntroducing new technologies without a strategyJava 8 + Java 21 features in one file
Political decisionsTechnology imposed from above without contextEnterprise framework for a simple script

The “Creativity” Factor

Experienced developers who want to try new technologies in production often become the source of Frankenstein. Instead of limiting experiments to an isolated module, they introduce experimental code into critical parts of the system.

Examples of Frankenstein in Real Projects

A classic example is using multiple ORMs in one application. Some modules use Hibernate, some use MyBatis, and some use raw JDBC queries. Transactions become unmanageable, cache becomes inconsistent, and a new developer doesn't know which approach to use for a new feature.

A second example is mixing architectural styles. In a REST API controller, you find SOAP service calls, raw SQL queries, file system access, and HTML generation. Such an application is impossible to test, extend, or document.

A third example is a tech stack where Python is used for the backend, Node.js for a microservice, C# for a desktop client, and Java for an Android app, while all business logic is smeared across them without clear separation of responsibilities.

javascript
// frankenstein — mixed styles and technologies
// callbacks, Promises, and async/await combined

// callbacks
db.query("SELECT * FROM users", function(err, rows) {
  if (err) handleError(err);
  // Promise inside callback
  fetch("/api/data").then(function(data) {
    // async/await inside then
    (async () => {
      const result = await processData(data);
      sendResponse(result);
    })();
  });
});

// clean code — unified async/await style
async function getUserData(userId) {
  const user = await db.query("SELECT * FROM users WHERE id = ?", [userId]);
  const data = await fetch("/api/data/" + userId);
  return await processData(user, data);
}

Frankenstein at the Data Level

A single database is used simultaneously as an SQL relational (with normalization) and as a NoSQL document-oriented (with JSON columns) one. Some queries go through ORM, some through stored procedures, some through raw SQL from code. The DB schema is undocumented, migrations conflict.

Consequences of Frankenstein Code

Onboarding complexity is the first consequence. A new developer must know 5 languages, 3 frameworks, 2 architectural styles to understand how the system works. Onboarding stretches from weeks to months. According to LinkedIn (2023), projects with technological eclecticism lose new employees 2 times more often.

Behavior unpredictability is the second consequence. A change in the Python microservice can unexpectedly break the Java module because they share a database without clear contracts. Debugging such problems requires simultaneous knowledge of all technologies in the stack.

Security is the third consequence. Each technology in the stack requires its own security configuration, its own patches, its own monitoring. Maintaining security at an acceptable level for 5-6 heterogeneous technologies is practically impossible. One of them will inevitably be vulnerable.

Frankenstein's Technical Debt

SonarQube can measure technical debt, but it cannot measure “architectural debt” — component incompatibility. This debt manifests not in linter warnings, but in the inability to add a new feature without modifying three different modules written in different technologies.

How to Avoid Creating a Monster

The first and main step is to appoint an architect or tech lead responsible for the integrity of the technology stack. This person has veto power over introducing new technologies without an architectural review. Not democracy, but responsible sole decision-making on key technologies.

The second step is to implement the Architecture Decision Record (ADR) process. Any significant architectural decision (DB choice, framework, protocol) is documented as a short text: context, alternatives considered, decision made, consequences. ADRs are stored in the repository and available to the entire team.

The third step is to establish the principle of “one task — one tool”. For HTTP requests — one client. For ORM — one library. For logging — one framework. Exceptions are allowed only through ADR with justification. If the project already has Axios — don't add fetch, if it has SLF4J — don't write via System.out.

  • Architect with veto power over new technologies
  • Architecture Decision Records for every significant choice
  • Unified stack for each task — one HTTP client, one ORM
  • RFC for major changes with team-wide discussion
  • Technology radar for tracking what can be adopted

Experimental Technology Policy

Experiments are allowed, but in an isolated environment. Allocate a module or service that can be rewritten with a new technology without affecting the rest of the system. If the experiment succeeds — standardize it via ADR. If not — remove it without consequences.

How to Refactor Existing Frankenstein

Inventory — the first step. Create a complete map of the technology stack: what frameworks, libraries, languages, protocols are used, in which modules and for what tasks. You will see the scale of the problem: tool duplication, conflicting technologies, unused dependencies.

Standardization — the second step. Choose one tool for each task. For example: only Hibernate for ORM, only SLF4J + Logback for logging, only REST for API. Document the standard in ADR. Start replacing from modules where eclecticism causes the most problems.

Parallel Run strategy — the third step. The old and new tools work in parallel until the new one proves its reliability. For example, the old HTTP client and the new one work simultaneously, but the new one only handles part of the requests. After a stabilization period, the old one is removed.

java
// frankenstein — three HTTP approaches in one project
// Module A: OkHttp
OkHttpClient client = new OkHttpClient().newCall(request);

// Module B: RestTemplate (Spring)
restTemplate.getForObject(url, String.class);

// Module C: java.net.HttpURLConnection
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();

// unified approach: RestTemplate for sync, WebClient for reactive
@Autowired
private RestTemplate restTemplate;

public String callApi(String url) {
    return restTemplate.getForObject(url, String.class);
}

The Role of a Technical Leader in Prevention

A technical leader is the main tool for fighting Frankenstein. Not a manager, not an architect in an ivory tower, but a practicing developer who writes code, reviews PRs, and makes architectural decisions. Without such a person, the project inevitably slides into technological eclecticism.

RFC (Request for Comments) is a process borrowed from Open Source communities. Before introducing any significant technology, the author writes an RFC: problem, proposed solution, alternatives, implementation plan. The team discusses, votes, accepts or rejects. RFC creates transparency and prevents “quiet” architectural decisions.

The Technology Radar (ThoughtWorks Technology Radar) is a categorization tool: Adopt, Trial, Assess, Hold. The team regularly reviews the radar and updates statuses. This helps distinguish “trendy” from “useful” and avoid introducing unproven technologies into critical code.

The Consistency Principle

The most important quality of architecture is consistency. Even the best tool used throughout the entire project is not better than the best tool used only in one module... Actually, even a not-so-great tool used throughout the entire project is better than the best tool used only in one module. Consistency reduces cognitive load, simplifies onboarding, and makes code predictable.

Frequently Asked Questions

How is Frankenstein different from using polyglot persistence?

Polyglot persistence is the conscious use of different databases for different tasks (PostgreSQL for transactions, Redis for caching, Elasticsearch for search). Frankenstein is chaotic mixing without strategy. The difference lies in having an architectural decision: polyglot is a plan, Frankenstein is its absence.

Can a microservice architecture turn into Frankenstein?

Yes, and this is a common problem. When each microservice uses its own language, its own database, its own protocol and its own deployment approach without centralized standards — you get a distributed Frankenstein. For microservices, common standards are important: a unified protocol (REST/gRPC), a common log format, centralized observability.

How to convince the team not to use a new technology?

Don't forbid — guide. Suggest the author write an RFC: describe why the existing solution doesn't fit, what alternatives were considered, how migration will be done. Often in the process of writing an RFC, the developer themselves realizes that the new technology is not needed. If the RFC is convincing — implement it, but with a plan and constraints.

How to deal with Frankenstein in a legacy project?

First, inventory, then standardization. Don't try to rewrite everything at once. Select one layer (e.g., HTTP clients or logging), pick a single tool, write an ADR, and migrate gradually. The Strangler Fig pattern — replace old components with new ones one by one without stopping the application.

How many technologies are optimal for one project?

The fewer, the better. Ideally — one language, one framework, one database, one logging method. Realistically — 2-3 languages (with clear separation), 1-2 databases, 1-2 frameworks. Each additional technology increases the team's cognitive load and maintenance cost.

Summary

  • Frankenstein is an antipattern where the system is assembled from heterogeneous incompatible components
  • Main causes: lack of an architect, project mergers, uncontrolled experiments
  • Consequences — complex onboarding, unpredictable behavior, security issues
  • ADR and RFC are key processes for preventing architectural eclecticism
  • The principle of “one tool per task” is the basis of prevention
  • Refactoring starts with inventory and standardization of the technology stack
  • Architecture consistency is more important than the “best tool” for one subtask

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also