Train under one engine, load under another
This is a Keras 3 superpower: save a model under one backend and load it under a completely different one. Train on JAX to get its fast JIT compilation, save the .keras file, then reopen it under TensorFlow to hand off to TF Serving — the file doesn't care which engine wrote it.
Why it works
The .keras format stores no backend-specific operations. It records the layer config and the weights as plain, backend-agnostic arrays — there's no traced JAX graph or frozen TF function baked in. So when a different backend loads the file, it rebuilds the same layers from the config and dispatches their math through its own keras.ops implementation. Numerically identical model, different engine underneath.
Where portability breaks
The guarantee holds as long as you stay inside Keras. If a layer reaches past keras.ops into a backend's native API — a raw tf.signal.fft call, a hand-written PyTorch op — that operation has no equivalent on the other backends, and the cross-backend load will fail there. The rule is simple: build models out of Keras layers and keras.ops, and portability is free; drop to native ops and you've pinned yourself to one engine.