Which Keras model API should a team standardize on across a shared codebase?
answer
- decide by consumers, not by taste
- architecture as config or as code
- reconstructing a model a year later
- layer the policy, do not pick one
- write the backend rule down
basics
~20 sThere is no universal answer, but a workable policy is: Functional as the default assembly layer, custom Layer subclasses as the extension point, Model subclassing reserved for genuinely dynamic forward passes, and Sequential kept for baselines. Decide on export, review and tooling needs rather than taste.
solid answer
~50 sFrame it by who consumes the models, not by which API is nicer to write. If models leave the training repo — exported, served, cut for transfer learning, reviewed by people who did not write them — the declarative APIs win, because a Functional topology is inspectable with `model.summary()`, drawable, sliceable with `get_layer(...).output`, and round-trips from configuration without importing the author's code. If the work is research where forward passes change weekly, subclassing wins on iteration speed. Most teams land on a layered policy: `keras.Sequential` for baselines and preprocessing stacks, the Functional API as the standard way to assemble a model, `keras.layers.Layer` subclasses as the sanctioned place for novel computation, and `keras.Model` subclassing allowed only where the forward pass is genuinely data-dependent — and then required to carry `get_config`/`from_config` and an explicit build. In Keras 3, add one more clause: custom code goes through `keras.ops` so the codebase is not silently pinned to one backend.
go deeper
You are unlikely to set the standard, but know that Functional models can be inspected and sliced while subclassed ones cannot, and that this is why teams often default to Functional for shared work.
Be able to argue from consequences rather than preference: what each API costs at export, review and reload time, and why a custom Layer inside a Functional graph usually covers the need to subclass at all.
Propose a concrete layered policy and its enforcement points, and say where you would not apply it. Name the reload dependency on importable code as the sharpest practical risk.
Own the criteria and the rollout. State the axes — consumers, reconstructability, reviewability, tooling, velocity, backend portability — weight them for this organisation, apply the standard at boundaries instead of by decree, and be explicit that a research-heavy team may rightly weigh them differently.
## Why this is a policy question, not a preference All three Keras model APIs train identically and reach identical accuracy. The differences are entirely about what happens to a model *after* it is written: who reads it, who exports it, who reuses half of it, and who is on call when it fails to load. That makes API choice an engineering-standards question with a real cost curve, which is why it is asked as a judgment question rather than a knowledge one. ## The axes that actually decide it **Who consumes the model.** A model that stays inside one notebook has no downstream consumers, and its author should use whatever is fastest to write. A model that is exported, served, versioned, or handed to another team acquires consumers who need to understand and manipulate it without reading its source. Declarative topologies serve those consumers; imperative ones require the code. **Reconstructability.** A Functional model's architecture is configuration. A subclassed model's architecture is a Python class that must be importable, at the right version, wherever the model is loaded. That is a real dependency between a stored artifact and a code repository, and it is the single most common cause of a model that cannot be reloaded a year later. **Reviewability.** A diff of a Functional model shows the graph changing. A diff of a subclassed `call()` shows control flow changing, and reviewers must simulate it mentally. For a team where models are reviewed like any other code, the declarative form is materially cheaper to review. **Tooling and instrumentation.** Feature extraction, transfer learning, activation debugging, perceptual losses and layer freezing all lean on addressing a named layer in a recorded graph. If any of these are part of the team's routine, giving them up across the codebase is a large recurring cost paid to save a small one-time cost. **Research velocity.** Against all of that: if the forward pass genuinely changes shape every week, forcing it through a declarative graph produces contorted code and slows the work the team exists to do. **Backend portability (Keras 3 specific).** Keras 3 runs on TensorFlow, JAX and PyTorch, selected by `KERAS_BACKEND`. Models built only from Keras layers are portable for free. Custom `call()` code is portable only if it stays within `keras.ops`. Without a stated rule, a team that believes it is multi-backend can discover late that half its custom layers are not. ## A policy that holds up 1. **Sequential** — baselines, ablations, preprocessing stacks. Cheap, obvious, no ceremony. Not a target for production models, because the first architectural change breaks it. 2. **Functional** — the default for anything shared. Every model that is exported, served or reused is assembled here. Every layer that anyone might want to address later gets an explicit `name`, because auto-generated names are not stable across refactors. 3. **Layer subclassing** — the sanctioned extension point. Novel computation goes into a `keras.layers.Layer` that a Functional graph then wires up. This captures nearly all of the expressiveness people reach for when they subclass a whole model. 4. **Model subclassing** — allowed, but by exception and with obligations: the forward pass must be genuinely value-dependent, the class must implement `get_config`/`from_config` so it round-trips, and it must be explicitly built (or smoke-tested with a dummy batch) so shape errors surface at import rather than mid-run. 5. **Custom numerics through `keras.ops`** — unless the team has consciously decided it is single-backend forever, in which case write that decision down rather than leaving it implicit. ## How to introduce it Do not retro-convert working models; the accuracy is identical, so the change buys nothing on its own and risks regressions. Apply the policy at the boundary instead: any model that becomes a shared dependency, gets exported, or acquires a second consumer is assembled functionally when it next changes. Existing research models keep their form until they graduate. ## The honest counter-argument A policy that is fought stops being a policy. If the team is overwhelmingly research-facing and models rarely leave, mandating Functional assembly is friction that buys tooling nobody uses. The defensible version of the decision is always conditional: name the consumers, name the operations the team performs on models, and let the standard follow from those. A principal who states the criteria and their weighting has answered the question; one who simply names a favourite API has not.
- What is the strongest single argument against allowing Model subclassing freely?The saved artifact stops being self-describing. Its architecture lives in a Python class that must be importable, at a compatible version, wherever the model is loaded — so reloading a model becomes a dependency on a code repository rather than on a file. That is the most common reason an old model cannot be restored.
- Would you retro-convert existing subclassed models to the Functional API?Not on its own. Accuracy and training behaviour are identical, so a bulk rewrite spends review time and risks regressions for no measurable gain. Apply the standard at the boundary: convert when a model gains a second consumer, gets exported, or is next substantially changed.
- How does Keras 3's multi-backend support change the standard?It adds a clause about custom code. Models built from Keras layers are portable across the TensorFlow, JAX and PyTorch backends for free, but custom forward-pass code is portable only if it stays within `keras.ops`. A team that believes it is backend-agnostic should state that rule explicitly, or record the decision that it is single-backend.
- How do you keep a Functional-first standard from slowing down research work?Scope it. Research and exploration keep whatever form is fastest; the standard binds only models that cross a boundary — shared, exported or served. Pair that with a sanctioned extension point, custom Layer subclasses, so researchers rarely need to give up expressiveness to comply.
saying these in an interview costs you the question
- Picking one API as universally correct with no criteria
- Claiming Functional models train faster than subclassed ones
- Mandating a bulk rewrite of working models for consistency alone
- Ignoring that a subclassed model needs its class to reload
- Assuming all custom Keras 3 code is backend-portable by default