Add Tensorflow pre-processing to existing Keras model for use in Tensorflow Serving
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
If an existing Keras model expects already-normalized tensors, but TensorFlow Serving will receive raw production inputs, the safest deployment move is to wrap the preprocessing into the served model itself. That keeps training-time and serving-time transformations aligned and removes the need for an external preprocessing service to stay perfectly in sync. In practice, you build a new model whose input matches the raw serving payload, apply preprocessing layers or TensorFlow ops, and then call the existing model.
Why Put Preprocessing Inside the Model
Serving failures often come from training and inference pipelines drifting apart. Maybe the training code resized images, rescaled pixels, normalized features, or encoded categories, but the serving endpoint receives raw values and forgets one of those steps.
Embedding preprocessing into the model solves that by making the exported SavedModel responsible for the entire input contract.
This is especially useful for:
- image resizing and scaling
- text tokenization or vocabulary lookup
- numerical normalization
- categorical lookup and encoding
Wrap an Existing Model With Image Preprocessing
Suppose the existing base model already expects tensors shaped (224, 224, 3) with pixel values in the 0..1 range.
You can wrap it with preprocessing layers so the served model accepts raw images instead.
Now the outer model owns both preprocessing and inference.
Adapt Stateful Preprocessing Before Export
Some preprocessing layers such as Normalization, StringLookup, or TextVectorization need to be adapted before saving.
The important detail is that the adapted state becomes part of the exported model, so serving uses the same normalization parameters learned during preparation.
Save for TensorFlow Serving
Once the wrapped model is ready, export it as a SavedModel.
If your environment uses an earlier Keras/TensorFlow export style, tf.saved_model.save or model.save(..., save_format="tf") may still appear in codebases, but the core idea is the same: export the wrapped model, not just the original base model.
TensorFlow Serving should then load the exported directory, and requests should match the raw input signature defined by the wrapper model.
Keep the Serving Signature Honest
The outer model's input shape and dtype define the serving contract. If the model expects raw uint8 images, the client must send that. If it expects raw floats or strings, the client must send those.
That means the preprocessing wrapper should not be vague. It should match the real production payload so the serving system and the model agree exactly about what “input” means.
When Not to Put Preprocessing in the Model
Sometimes external preprocessing is still appropriate, especially when it depends on systems or logic that cannot sensibly live inside a TensorFlow graph. But for deterministic transformations that must be identical between training and serving, embedding them in the model is usually the safer architecture.
The key is choosing one owner for the input contract and making that ownership explicit.
Common Pitfalls
- Exporting the original model and forgetting that it still expects already-preprocessed tensors.
- Adding preprocessing layers but forgetting to adapt stateful layers such as
Normalizationbefore saving. - Defining a serving input signature that does not match the actual raw production payload.
- Keeping part of the preprocessing outside the model and part inside, which recreates the drift problem you were trying to remove.
- Treating TensorFlow Serving export as a deployment step only, rather than as part of defining the model's true inference contract.
Summary
- To use raw production inputs safely in TensorFlow Serving, wrap preprocessing into the exported Keras model.
- The wrapper model should accept the real serving payload and then call the existing base model.
- Preprocessing layers such as resizing, rescaling, normalization, and lookup layers fit naturally in this pattern.
- Export the wrapped model, not only the original inference core.
- The goal is one consistent input contract across training, export, and serving.

