tolgacelik.net
All posts
·3 min read

Polyglot Architecture: Java, .NET, and Python on One Platform

Our production platform has 20+ microservices — some Java/Spring, some .NET Core, some Python. Can multiple languages live next to each other cleanly? When is it necessary, when is it regret?

polyglotjavadotnetpythonarchitecture

"Pick one language, write everything in it" is a common piece of advice. It sounds reasonable: your team learns one language, tooling is unified, debugging always looks the same. In production systems this isn't always possible — and often shouldn't be.

Our platform runs Java, .NET Core, PHP, Python, and Node.js in production at the same time. This wasn't a historical accident; it was a deliberate choice. This post walks through when polyglot architecture makes sense, and when it turns into regret.

Why multiple languages?

First reason: different languages have different ecosystems. Each language has areas where it's strongest; forcing an alternative is wasted effort.

Examples from our system:

  • Java (Spring) — mature game server frameworks, plenty of domain code, strong typing. Great fit for core game logic.
  • .NET Core — some game server variants and API services. Certain third-party integrations are smoother on .NET.
  • Python — async consumer services, data processing, ML integrations. Ecosystem clearly ahead here.
  • Node.js — WebSocket-based real-time facades. Event-loop model suits these workloads well.

Is keeping four languages running together difficult? Absolutely. But because each is used where it's actually needed, it's worth it.

Second reason: team composition

A Java dev joining the team shouldn't be told "write .NET from now on." The same way, a Python data team told "migrate to Java" is asked to throw away half their data-science capital.

Polyglot architecture lets you scale the team as they are. "Do we need a Java specialist or a Python specialist?" can be decided on technical merit, not the constraint that "everyone must know Java."

Where polyglot earns its keep

1. Language-specific library needs

  • ML in Python (PyTorch, scikit-learn)
  • Specialized game frameworks in Java
  • Windows/Microsoft integrations in .NET

2. Performance profile

  • CPU-heavy work often fits Rust/Go better
  • I/O-heavy work suits Node.js/Python
  • JVM workloads have the most mature tooling in Java

3. Expertise

  • A strong team in a given language shouldn't be forced off it

But flexibility has a cost

Polyglot isn't "free." At minimum, you pay along three dimensions:

1. Operational complexity

Each language brings its own:

  • Package manager (Maven/NuGet/pip/npm)
  • Runtime characteristics (JVM warm-up, Python GIL, Node event loop)
  • Performance tuning tools
  • Deployment rules (Dockerfile, Helm chart)

This takes more investment than a single-language team. I don't recommend polyglot for small teams.

2. Observability

Tracing, logging, and metrics work differently in each language. OpenTelemetry narrows this, but doesn't close it. Sentry integration differs, log format differs, exception stack traces differ.

Solution: the platform team enforces minimum consistency. For example:

  • All logs in JSON
  • All logs include the same 5 fields minimum
  • Every service exposes /health and /metrics with a shared shape

Without these standards, polyglot observability scatters.

3. Reusable code

A module the Java team writes can't be used by the Python team. This means writing the same logic in two languages is sometimes necessary. Our answer: shared primitives as services. E.g. auth is a service, Java and Python both call it.

Not shared libraries — shared services. Language-independent.

When NOT to do polyglot

One rule I'm strict about: don't do polyglot in a small team. A 5-person team can't run four languages well. Every developer ends up chasing bugs across all four per week. Burnout is guaranteed.

Polyglot makes sense: 15+ developers, at least 2–3 teams, a platform team, clear "owner" for each language. That's our situation.

Polyglot is destructive: 3 devs, everyone doing everything, and opening a service by someone else means being exposed to yet another language's rituals.

Standardization: where yes, where no

What we standardize:

  • Container build (Dockerfile pattern)
  • Deployment (Helm chart template)
  • Log format (JSON + common fields)
  • Health endpoint shape
  • CI/CD pipeline
  • Secret management (vault)

What we don't:

  • Language choice (team decides)
  • Internal framework architecture (each team picks)
  • Test strategy (frameworks differ, but 80% coverage is mandatory)

Finding this balance took time. Early we had too many rules (teams pushed back), then too few (chaos). The current set is steady.

Takeaway

Polyglot architecture isn't freedom — it's responsibility. Managed well, it multiplies team productivity. Managed badly, it slows the team. The decision criterion is simple: do you have a clear answer to "why this language?" If not, you probably made an unnecessary choice.

Single-language is nice; polyglot is fitting. Both are good in their right place.

ShareLinkedInX
Get the next one in your inbox

Long-form notes on distributed systems, production stability, AI-assisted shipping. No spam, easy to unsubscribe.

Email only. Stored on this server. Never sold or shared.

Comments

No comments yet. Be the first.

Leave a comment

Never shown publicly. Only used if I need to reply.