Cannot freeze Tensorflow models into frozen.pb file
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Freezing a TensorFlow model into a single frozen.pb file used to be a common TensorFlow 1.x deployment step. In TensorFlow 2.x, that workflow is no longer the default, so attempts to "freeze the model" often fail because the code still assumes sessions, checkpoints, and graph utilities from the older API.
What A Frozen Graph Actually Is
A frozen graph is a graph definition where variable values have been converted into constants embedded in the graph itself. In TensorFlow 1.x, that made it easier to ship a single .pb file for inference.
Today, TensorFlow prefers SavedModel, which keeps more structure and works better with serving, signatures, and modern tooling. That means the first question is not "how do I freeze," but "do I actually need a frozen graph, or would SavedModel solve the problem better?"
Prefer SavedModel When Possible
If your deployment target accepts modern TensorFlow artifacts, export the model directly.
That is the clean path for TensorFlow Serving and many TensorFlow 2.x workflows.
Freezing In TensorFlow 2.x
If you truly need a frozen .pb, the usual TensorFlow 2.x route is:
- build a concrete function from the model
- convert variables to constants
- serialize the frozen graph definition
That produces a serialized graph definition suitable for graph-based inference scenarios.
Why Old Freezing Code Often Breaks
Older tutorials rely on APIs such as:
- '
tf.Session()' - '
tf.graph_util.convert_variables_to_constants' - checkpoint restoration into the default graph
Those patterns belong to TensorFlow 1.x graph execution. In TensorFlow 2.x, eager execution is enabled by default, so there is no persistent session-driven default path to freeze in the same way.
If the code mixes Keras model objects with old session utilities, the result is often confusion about missing graph nodes, uninitialized variables, or incompatible APIs.
Input Signatures Matter
When freezing fails, the real issue is often the exported function signature rather than the conversion step itself. The freezing utility needs a concrete function with known input structure.
A vague or mismatched signature can produce a graph that does not match your intended inference input.
Freezing Custom Layers Or Training Logic
Custom layers usually freeze correctly if they are built from TensorFlow ops and variables. Problems start when the model relies on Python-side control flow, external state, or training-only logic that never became part of the traced inference function.
That is another reason SavedModel is usually safer: it preserves more of the intended runtime behavior and signatures.
When A Frozen .pb Is Still Useful
A frozen graph can still be useful for legacy C++ inference pipelines, older deployment tools, or ecosystems that expect a graph-only artifact. But it is now a compatibility format, not the primary TensorFlow export format.
That distinction matters because many errors come from treating frozen graphs as the normal endpoint of every TensorFlow model.
Common Pitfalls
The most common mistake is using TensorFlow 1.x freezing code against a TensorFlow 2.x eager model. Another is trying to freeze before the model variables exist, which is why running the model once or building it explicitly matters. Developers also often forget to create a concrete function with the correct input signature. Finally, many deployment problems disappear if the target can consume SavedModel, so do not choose frozen .pb out of habit alone.
Summary
- '
SavedModelis the preferred export format in modern TensorFlow.' - If you truly need
frozen.pb, freeze a concrete function withconvert_variables_to_constants_v2. - Old session-based freezing code usually belongs to TensorFlow 1.x.
- Build the model and define a concrete input signature before freezing.
- Treat frozen graphs as a legacy compatibility format, not the default deployment target.

