Python
TensorFlow
.NET
Integration
Machine Learning

Integrate Python based TensorFlow into a .NET application

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

If your model is built in Python with TensorFlow and your application is written in .NET, the cleanest integration is usually not "embed Python inside the .NET process". In most production systems, you either expose the TensorFlow model through a service or export it into a format that a .NET-friendly runtime can consume.

Choose an Integration Strategy First

There are three broad patterns:

  • keep TensorFlow in Python and call it through HTTP or gRPC
  • export the trained model and load it from a .NET inference runtime
  • embed Python directly, which is possible but usually the hardest to maintain

The service boundary is often the safest choice because it separates language environments cleanly. The exported-model route can be great when latency matters and the model format is compatible. In-process Python integration tends to create the most dependency pain.

Python Service Pattern

A common architecture is:

  1. train the model in Python
  2. load it in a lightweight Python API service
  3. call that service from .NET

Here is a minimal Python inference service using FastAPI:

python
1import numpy as np
2import tensorflow as tf
3from fastapi import FastAPI
4from pydantic import BaseModel
5
6app = FastAPI()
7model = tf.keras.models.load_model("saved_model.keras")
8
9
10class PredictRequest(BaseModel):
11    features: list[float]
12
13
14@app.post("/predict")
15def predict(request: PredictRequest):
16    batch = np.asarray([request.features], dtype=np.float32)
17    scores = model.predict(batch, verbose=0)
18    return {"prediction": int(np.argmax(scores[0]))}

This keeps TensorFlow where it is most natural and lets the .NET app stay focused on business logic.

Call the Model From .NET

The .NET side can treat the model as an external dependency and call it with HttpClient.

csharp
1using System.Net.Http.Json;
2
3var client = new HttpClient
4{
5    BaseAddress = new Uri("http://localhost:8000")
6};
7
8var response = await client.PostAsJsonAsync("/predict", new
9{
10    features = new[] { 0.12f, 0.34f, 0.56f }
11});
12
13var result = await response.Content.ReadFromJsonAsync<PredictionResponse>();
14Console.WriteLine(result?.Prediction);
15
16public record PredictionResponse(int Prediction);

This pattern is straightforward to deploy, version, and monitor. It also avoids shipping Python, TensorFlow, CUDA, and related native dependencies inside the .NET application itself.

Exported Model Pattern

If you need the model to run closer to the .NET process, another route is to export the trained model into an inference-friendly format and use a .NET-compatible runtime. The viability of this approach depends on:

  • the TensorFlow model type
  • the export path you choose
  • the operators the target runtime supports

This can reduce network hops, but it usually introduces more conversion and compatibility work during the deployment pipeline.

Avoid In-Process Python Unless You Truly Need It

Some teams try to host Python inside the .NET process so they can call TensorFlow functions directly. That can work, but it tends to create problems around:

  • environment management
  • native library compatibility
  • process startup behavior
  • thread and memory isolation
  • deployment reproducibility

Unless there is a hard requirement for direct in-process calls, a service or exported-model approach is usually easier to test and operate.

Version the Contract, Not Just the Model

No matter which integration method you choose, define the model contract clearly. That means fixing:

  • input feature order
  • data types
  • normalization rules
  • output schema
  • model version

A mismatch in preprocessing is one of the most common reasons a technically successful integration still produces wrong predictions.

Common Pitfalls

The biggest mistake is treating integration as a library problem only. In practice, preprocessing, output shape, model versioning, and deployment boundaries matter just as much as the TensorFlow call itself.

Another common issue is loading the Python model on every request. Whether the model lives in a Python service or another runtime, it should usually be loaded once and reused.

People also underestimate dependency complexity when they try to embed Python directly in a .NET app. Native TensorFlow builds, CUDA libraries, and environment drift can turn a simple demo into an operational burden.

Finally, do not skip validation of the request and response schema. A .NET client and a Python model can both be correct in isolation and still disagree on feature order or numeric types.

Summary

  • The cleanest integration is often a Python inference service called from .NET.
  • Exported-model runtimes can work well when low latency or local inference matters.
  • In-process Python integration is usually the hardest option to maintain.
  • Define preprocessing and output contracts explicitly so predictions stay correct.
  • Load the model once per process rather than once per request.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.