[{"data":1,"prerenderedAt":1313},["ShallowReactive",2],{"article-five-things-break-notebook-to-production":3,"content-query-zJmclQHMTt":745},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"body":11,"_type":739,"_id":740,"_source":741,"_file":742,"_stem":743,"_extension":744},"\u002Farticles\u002Ffive-things-break-notebook-to-production","articles",false,"","Five Things That Break When You Move a Model From Notebook to Production","The gap between a working notebook and a working production model is filled with subtle failures. Here are the five most common ones and how to fix them.","2025-07-14",{"type":12,"children":13,"toc":719},"root",[14,22,28,33,40,45,50,60,73,80,109,120,140,151,172,178,183,194,207,212,256,261,274,283,304,309,315,320,325,376,381,386,395,404,409,414,420,425,430,473,478,483,492,497,506,511,517,538,543,548,561,570,575,647,652,657,666,671,677,682,687,692,696],{"type":15,"tag":16,"props":17,"children":19},"element","h1",{"id":18},"five-things-that-break-when-you-move-a-model-from-notebook-to-production",[20],{"type":21,"value":8},"text",{"type":15,"tag":23,"props":24,"children":25},"p",{},[26],{"type":21,"value":27},"Your model works in a notebook. The accuracy is good, the plots look right, your colleagues are impressed. You decide to deploy it.",{"type":15,"tag":23,"props":29,"children":30},{},[31],{"type":21,"value":32},"Then things break — not dramatically, but in quiet, frustrating ways. The predictions are wrong but not obviously wrong. The service crashes under load. The model works on your machine but not in the container. These are the most common failure modes, and they're all avoidable.",{"type":15,"tag":34,"props":35,"children":37},"h2",{"id":36},"_1-dependency-mismatches",[38],{"type":21,"value":39},"1. Dependency mismatches",{"type":15,"tag":23,"props":41,"children":42},{},[43],{"type":21,"value":44},"The notebook runs on your machine with whatever packages you've installed over the past year. The production environment is different — different Python version, different library versions, different OS.",{"type":15,"tag":23,"props":46,"children":47},{},[48],{"type":21,"value":49},"The classic symptom: the model loads fine but produces different predictions. Or it throws a cryptic deserialization error.",{"type":15,"tag":51,"props":52,"children":54},"pre",{"code":53},"ModuleNotFoundError: No module named 'sklearn.ensemble._forest'\n",[55],{"type":15,"tag":56,"props":57,"children":58},"code",{"__ignoreMap":7},[59],{"type":21,"value":53},{"type":15,"tag":23,"props":61,"children":62},{},[63,65,71],{"type":21,"value":64},"This happens when you train with scikit-learn 1.3 and try to load the pickle with scikit-learn 1.2. The internal module paths changed between versions, and ",{"type":15,"tag":56,"props":66,"children":68},{"className":67},[],[69],{"type":21,"value":70},"pickle",{"type":21,"value":72}," serializes the full path.",{"type":15,"tag":74,"props":75,"children":77},"h3",{"id":76},"the-fix",[78],{"type":21,"value":79},"The fix",{"type":15,"tag":23,"props":81,"children":82},{},[83,85,91,93,99,101,107],{"type":21,"value":84},"Pin every dependency with exact versions. Not ",{"type":15,"tag":56,"props":86,"children":88},{"className":87},[],[89],{"type":21,"value":90},"scikit-learn>=1.0",{"type":21,"value":92},", not ",{"type":15,"tag":56,"props":94,"children":96},{"className":95},[],[97],{"type":21,"value":98},"scikit-learn~=1.3",{"type":21,"value":100},". Use ",{"type":15,"tag":56,"props":102,"children":104},{"className":103},[],[105],{"type":21,"value":106},"scikit-learn==1.3.2",{"type":21,"value":108},".",{"type":15,"tag":51,"props":110,"children":115},{"code":111,"language":112,"meta":7,"className":113},"pip freeze > requirements.txt\n","bash",[114],"language-bash",[116],{"type":15,"tag":56,"props":117,"children":118},{"__ignoreMap":7},[119],{"type":21,"value":111},{"type":15,"tag":23,"props":121,"children":122},{},[123,125,131,133,138],{"type":21,"value":124},"Better yet, use the same Docker image for training and serving. If the model was trained in ",{"type":15,"tag":56,"props":126,"children":128},{"className":127},[],[129],{"type":21,"value":130},"python:3.11-slim",{"type":21,"value":132}," with ",{"type":15,"tag":56,"props":134,"children":136},{"className":135},[],[137],{"type":21,"value":106},{"type":21,"value":139},", serve it from the same image. This eliminates version mismatches entirely.",{"type":15,"tag":51,"props":141,"children":146},{"code":142,"language":143,"meta":7,"className":144},"FROM python:3.11-slim\nCOPY requirements.txt .\nRUN pip install --no-cache-dir -r requirements.txt\nCOPY serve.py model\u002F\nCMD [\"python\", \"serve.py\"]\n","dockerfile",[145],"language-dockerfile",[147],{"type":15,"tag":56,"props":148,"children":149},{"__ignoreMap":7},[150],{"type":21,"value":142},{"type":15,"tag":23,"props":152,"children":153},{},[154,156,162,164,170],{"type":21,"value":155},"MLflow helps here too — it logs the ",{"type":15,"tag":56,"props":157,"children":159},{"className":158},[],[160],{"type":21,"value":161},"conda.yaml",{"type":21,"value":163}," or ",{"type":15,"tag":56,"props":165,"children":167},{"className":166},[],[168],{"type":21,"value":169},"requirements.txt",{"type":21,"value":171}," alongside the model artifact, so you can always reconstruct the exact environment that produced a model.",{"type":15,"tag":34,"props":173,"children":175},{"id":174},"_2-missing-preprocessing-steps",[176],{"type":21,"value":177},"2. Missing preprocessing steps",{"type":15,"tag":23,"props":179,"children":180},{},[181],{"type":21,"value":182},"This one is insidious. Your notebook has a cell that normalizes the data:",{"type":15,"tag":51,"props":184,"children":189},{"code":185,"language":186,"meta":7,"className":187},"from sklearn.preprocessing import StandardScaler\n\nscaler = StandardScaler()\nX_train_scaled = scaler.fit_transform(X_train)\nX_test_scaled = scaler.transform(X_test)\n\nmodel.fit(X_train_scaled, y_train)\n","python",[188],"language-python",[190],{"type":15,"tag":56,"props":191,"children":192},{"__ignoreMap":7},[193],{"type":21,"value":185},{"type":15,"tag":23,"props":195,"children":196},{},[197,199,205],{"type":21,"value":198},"The model is trained on scaled data. It expects scaled inputs. But the serving code receives raw features and passes them directly to ",{"type":15,"tag":56,"props":200,"children":202},{"className":201},[],[203],{"type":21,"value":204},"model.predict()",{"type":21,"value":206},". The predictions are garbage, but the model doesn't throw an error — it just returns wrong answers confidently.",{"type":15,"tag":23,"props":208,"children":209},{},[210],{"type":21,"value":211},"Variations of this problem:",{"type":15,"tag":213,"props":214,"children":215},"ul",{},[216,228,246],{"type":15,"tag":217,"props":218,"children":219},"li",{},[220,226],{"type":15,"tag":221,"props":222,"children":223},"strong",{},[224],{"type":21,"value":225},"Feature encoding",{"type":21,"value":227}," trained in the notebook but missing in production. Categorical variables that were one-hot encoded during training arrive as raw strings at serving time.",{"type":15,"tag":217,"props":229,"children":230},{},[231,236,238,244],{"type":15,"tag":221,"props":232,"children":233},{},[234],{"type":21,"value":235},"Feature engineering",{"type":21,"value":237}," done in a notebook cell that nobody copied to the serving code. The model expects a ",{"type":15,"tag":56,"props":239,"children":241},{"className":240},[],[242],{"type":21,"value":243},"price_per_sqft",{"type":21,"value":245}," feature that only exists in the notebook.",{"type":15,"tag":217,"props":247,"children":248},{},[249,254],{"type":15,"tag":221,"props":250,"children":251},{},[252],{"type":21,"value":253},"Missing imputation.",{"type":21,"value":255}," The notebook filled NaN values with the column median. The serving code passes NaN values through, and the model does something unpredictable.",{"type":15,"tag":74,"props":257,"children":259},{"id":258},"the-fix-1",[260],{"type":21,"value":79},{"type":15,"tag":23,"props":262,"children":263},{},[264,266,272],{"type":21,"value":265},"Bundle preprocessing with the model. Use a scikit-learn ",{"type":15,"tag":56,"props":267,"children":269},{"className":268},[],[270],{"type":21,"value":271},"Pipeline",{"type":21,"value":273},":",{"type":15,"tag":51,"props":275,"children":278},{"code":276,"language":186,"meta":7,"className":277},"from sklearn.pipeline import Pipeline\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.ensemble import RandomForestClassifier\n\npipeline = Pipeline([\n    (\"scaler\", StandardScaler()),\n    (\"classifier\", RandomForestClassifier(n_estimators=100)),\n])\n\npipeline.fit(X_train, y_train)\n",[188],[279],{"type":15,"tag":56,"props":280,"children":281},{"__ignoreMap":7},[282],{"type":21,"value":276},{"type":15,"tag":23,"props":284,"children":285},{},[286,288,294,296,302],{"type":21,"value":287},"Now ",{"type":15,"tag":56,"props":289,"children":291},{"className":290},[],[292],{"type":21,"value":293},"pipeline.predict(X_raw)",{"type":21,"value":295}," handles scaling internally. The serving code doesn't need to know about preprocessing — it just calls ",{"type":15,"tag":56,"props":297,"children":299},{"className":298},[],[300],{"type":21,"value":301},"predict()",{"type":21,"value":303}," on whatever comes in.",{"type":15,"tag":23,"props":305,"children":306},{},[307],{"type":21,"value":308},"For more complex preprocessing (text tokenization, image resizing, feature engineering), the same principle applies: serialize the entire transformation chain, not just the model. If preprocessing can't be part of the model object, make it a separate artifact that gets deployed alongside the model with an explicit contract between the two.",{"type":15,"tag":34,"props":310,"children":312},{"id":311},"_3-no-input-validation",[313],{"type":21,"value":314},"3. No input validation",{"type":15,"tag":23,"props":316,"children":317},{},[318],{"type":21,"value":319},"In the notebook, you control the input. You loaded the dataset, cleaned it, and shaped it correctly. In production, input comes from users, APIs, and upstream services — and it will be wrong in ways you didn't anticipate.",{"type":15,"tag":23,"props":321,"children":322},{},[323],{"type":21,"value":324},"Common failures:",{"type":15,"tag":213,"props":326,"children":327},{},[328,338,348,358],{"type":15,"tag":217,"props":329,"children":330},{},[331,336],{"type":15,"tag":221,"props":332,"children":333},{},[334],{"type":21,"value":335},"Wrong number of features.",{"type":21,"value":337}," The model expects 10 features, the request sends 9. NumPy reshapes silently and the prediction is meaningless.",{"type":15,"tag":217,"props":339,"children":340},{},[341,346],{"type":15,"tag":221,"props":342,"children":343},{},[344],{"type":21,"value":345},"Wrong data types.",{"type":21,"value":347}," A feature that should be float arrives as a string. Or an integer arrives as a float with a decimal point.",{"type":15,"tag":217,"props":349,"children":350},{},[351,356],{"type":15,"tag":221,"props":352,"children":353},{},[354],{"type":21,"value":355},"Out-of-range values.",{"type":21,"value":357}," The model was trained on ages between 18 and 90. A request arrives with age = -1 or age = 500.",{"type":15,"tag":217,"props":359,"children":360},{},[361,366,368,374],{"type":15,"tag":221,"props":362,"children":363},{},[364],{"type":21,"value":365},"Missing fields.",{"type":21,"value":367}," An optional field in the API is omitted and arrives as ",{"type":15,"tag":56,"props":369,"children":371},{"className":370},[],[372],{"type":21,"value":373},"None",{"type":21,"value":375},", which propagates through the model as NaN.",{"type":15,"tag":74,"props":377,"children":379},{"id":378},"the-fix-2",[380],{"type":21,"value":79},{"type":15,"tag":23,"props":382,"children":383},{},[384],{"type":21,"value":385},"Validate at the API boundary. Define the expected schema and reject bad input before it reaches the model.",{"type":15,"tag":51,"props":387,"children":390},{"code":388,"language":186,"meta":7,"className":389},"from pydantic import BaseModel, validator\nfrom typing import List\n\nclass PredictionRequest(BaseModel):\n    features: List[float]\n\n    @validator(\"features\")\n    def check_feature_count(cls, v):\n        if len(v) != 4:\n            raise ValueError(f\"Expected 4 features, got {len(v)}\")\n        return v\n",[188],[391],{"type":15,"tag":56,"props":392,"children":393},{"__ignoreMap":7},[394],{"type":21,"value":388},{"type":15,"tag":51,"props":396,"children":399},{"code":397,"language":186,"meta":7,"className":398},"from fastapi import FastAPI, HTTPException\n\napp = FastAPI()\n\n@app.post(\"\u002Fpredict\")\ndef predict(request: PredictionRequest):\n    try:\n        result = model.predict([request.features])\n        return {\"prediction\": int(result[0])}\n    except Exception as e:\n        raise HTTPException(status_code=500, detail=str(e))\n",[188],[400],{"type":15,"tag":56,"props":401,"children":402},{"__ignoreMap":7},[403],{"type":21,"value":397},{"type":15,"tag":23,"props":405,"children":406},{},[407],{"type":21,"value":408},"This returns a clear 422 error when input is wrong, instead of returning a wrong prediction that's indistinguishable from a correct one.",{"type":15,"tag":23,"props":410,"children":411},{},[412],{"type":21,"value":413},"Validation isn't glamorous, but it's the difference between \"the model is broken\" (it isn't — the input is wrong) and \"bad request, here's what you need to fix.\"",{"type":15,"tag":34,"props":415,"children":417},{"id":416},"_4-no-logging-or-monitoring",[418],{"type":21,"value":419},"4. No logging or monitoring",{"type":15,"tag":23,"props":421,"children":422},{},[423],{"type":21,"value":424},"In the notebook, you see the predictions right there in the output cell. In production, the model runs inside a service, receives requests, and returns responses — and nobody is watching.",{"type":15,"tag":23,"props":426,"children":427},{},[428],{"type":21,"value":429},"Without logging, you can't answer basic questions:",{"type":15,"tag":213,"props":431,"children":432},{},[433,443,453,463],{"type":15,"tag":217,"props":434,"children":435},{},[436,441],{"type":15,"tag":221,"props":437,"children":438},{},[439],{"type":21,"value":440},"Is the model being used?",{"type":21,"value":442}," How many predictions per day? Is traffic increasing or decreasing?",{"type":15,"tag":217,"props":444,"children":445},{},[446,451],{"type":15,"tag":221,"props":447,"children":448},{},[449],{"type":21,"value":450},"What is it predicting?",{"type":21,"value":452}," If the model starts predicting the same class for every input, that's a problem — but you won't know without logging.",{"type":15,"tag":217,"props":454,"children":455},{},[456,461],{"type":15,"tag":221,"props":457,"children":458},{},[459],{"type":21,"value":460},"How fast is it?",{"type":21,"value":462}," If prediction latency spikes from 10ms to 500ms, users notice before you do.",{"type":15,"tag":217,"props":464,"children":465},{},[466,471],{"type":15,"tag":221,"props":467,"children":468},{},[469],{"type":21,"value":470},"Is the input distribution changing?",{"type":21,"value":472}," If the average feature values shift significantly from training data, the model's predictions become unreliable. This is data drift.",{"type":15,"tag":74,"props":474,"children":476},{"id":475},"the-fix-3",[477],{"type":21,"value":79},{"type":15,"tag":23,"props":479,"children":480},{},[481],{"type":21,"value":482},"Log predictions, inputs (or summaries of inputs), and latency from day one.",{"type":15,"tag":51,"props":484,"children":487},{"code":485,"language":186,"meta":7,"className":486},"import time\nimport logging\n\nlogger = logging.getLogger(\"model-serving\")\n\n@app.post(\"\u002Fpredict\")\ndef predict(request: PredictionRequest):\n    start = time.time()\n\n    result = model.predict([request.features])\n    prediction = int(result[0])\n\n    latency = time.time() - start\n    logger.info(\n        \"prediction\",\n        extra={\n            \"prediction\": prediction,\n            \"feature_count\": len(request.features),\n            \"latency_ms\": round(latency * 1000, 2),\n        },\n    )\n\n    return {\"prediction\": prediction}\n",[188],[488],{"type":15,"tag":56,"props":489,"children":490},{"__ignoreMap":7},[491],{"type":21,"value":485},{"type":15,"tag":23,"props":493,"children":494},{},[495],{"type":21,"value":496},"For metrics, expose a Prometheus endpoint:",{"type":15,"tag":51,"props":498,"children":501},{"code":499,"language":186,"meta":7,"className":500},"from prometheus_client import Histogram, Counter\n\nPREDICTION_LATENCY = Histogram(\n    \"prediction_latency_seconds\",\n    \"Time spent processing prediction\",\n)\nPREDICTION_COUNT = Counter(\n    \"predictions_total\",\n    \"Total predictions\",\n    [\"predicted_class\"],\n)\n\n@app.post(\"\u002Fpredict\")\ndef predict(request: PredictionRequest):\n    with PREDICTION_LATENCY.time():\n        result = model.predict([request.features])\n        prediction = int(result[0])\n\n    PREDICTION_COUNT.labels(predicted_class=str(prediction)).inc()\n    return {\"prediction\": prediction}\n",[188],[502],{"type":15,"tag":56,"props":503,"children":504},{"__ignoreMap":7},[505],{"type":21,"value":499},{"type":15,"tag":23,"props":507,"children":508},{},[509],{"type":21,"value":510},"You don't need a full observability platform on day one. Structured logs and a few Prometheus metrics get you surprisingly far. The key is having them from the start — retrofitting monitoring after a production incident is stressful.",{"type":15,"tag":34,"props":512,"children":514},{"id":513},"_5-works-on-my-machine-deployment",[515],{"type":21,"value":516},"5. \"Works on my machine\" deployment",{"type":15,"tag":23,"props":518,"children":519},{},[520,522,528,530,536],{"type":21,"value":521},"The model works locally. You ",{"type":15,"tag":56,"props":523,"children":525},{"className":524},[],[526],{"type":21,"value":527},"scp",{"type":21,"value":529}," the model file and the serving script to a VM, run ",{"type":15,"tag":56,"props":531,"children":533},{"className":532},[],[534],{"type":21,"value":535},"python serve.py",{"type":21,"value":537},", and it works. Three weeks later the VM is rebooted, Python is updated by a system package upgrade, and the service doesn't come back up.",{"type":15,"tag":23,"props":539,"children":540},{},[541],{"type":21,"value":542},"Or: you hand the model to the platform team and say \"deploy this.\" They ask: \"How? What Python version? What dependencies? Does it need a GPU? How much memory? What port? What's the health check endpoint?\" You don't know the answers to half of these.",{"type":15,"tag":74,"props":544,"children":546},{"id":545},"the-fix-4",[547],{"type":21,"value":79},{"type":15,"tag":23,"props":549,"children":550},{},[551,553,559],{"type":21,"value":552},"Containerize the entire serving stack. A ",{"type":15,"tag":56,"props":554,"children":556},{"className":555},[],[557],{"type":21,"value":558},"Dockerfile",{"type":21,"value":560}," is a deployment specification — it captures everything needed to run the model.",{"type":15,"tag":51,"props":562,"children":565},{"code":563,"language":143,"meta":7,"className":564},"FROM python:3.11-slim\n\nWORKDIR \u002Fapp\nCOPY requirements.txt .\nRUN pip install --no-cache-dir -r requirements.txt\n\nCOPY serve.py .\nCOPY model\u002F model\u002F\n\nEXPOSE 8000\nHEALTHCHECK CMD curl -f http:\u002F\u002Flocalhost:8000\u002Fhealth || exit 1\n\nCMD [\"uvicorn\", \"serve:app\", \"--host\", \"0.0.0.0\", \"--port\", \"8000\"]\n",[145],[566],{"type":15,"tag":56,"props":567,"children":568},{"__ignoreMap":7},[569],{"type":21,"value":563},{"type":15,"tag":23,"props":571,"children":572},{},[573],{"type":21,"value":574},"This answers every question the platform team had:",{"type":15,"tag":213,"props":576,"children":577},{},[578,588,603,621,631],{"type":15,"tag":217,"props":579,"children":580},{},[581,586],{"type":15,"tag":221,"props":582,"children":583},{},[584],{"type":21,"value":585},"Python version:",{"type":21,"value":587}," 3.11",{"type":15,"tag":217,"props":589,"children":590},{},[591,596,598],{"type":15,"tag":221,"props":592,"children":593},{},[594],{"type":21,"value":595},"Dependencies:",{"type":21,"value":597}," pinned in ",{"type":15,"tag":56,"props":599,"children":601},{"className":600},[],[602],{"type":21,"value":169},{"type":15,"tag":217,"props":604,"children":605},{},[606,611,613,619],{"type":15,"tag":221,"props":607,"children":608},{},[609],{"type":21,"value":610},"GPU:",{"type":21,"value":612}," not needed (if it were, use ",{"type":15,"tag":56,"props":614,"children":616},{"className":615},[],[617],{"type":21,"value":618},"nvidia\u002Fcuda",{"type":21,"value":620}," base image)",{"type":15,"tag":217,"props":622,"children":623},{},[624,629],{"type":15,"tag":221,"props":625,"children":626},{},[627],{"type":21,"value":628},"Port:",{"type":21,"value":630}," 8000",{"type":15,"tag":217,"props":632,"children":633},{},[634,639,641],{"type":15,"tag":221,"props":635,"children":636},{},[637],{"type":21,"value":638},"Health check:",{"type":21,"value":640}," ",{"type":15,"tag":56,"props":642,"children":644},{"className":643},[],[645],{"type":21,"value":646},"GET \u002Fhealth",{"type":15,"tag":23,"props":648,"children":649},{},[650],{"type":21,"value":651},"The container runs the same way everywhere — on the developer's laptop, in CI, in staging, in production. The \"works on my machine\" problem is eliminated.",{"type":15,"tag":23,"props":653,"children":654},{},[655],{"type":21,"value":656},"Add a health check endpoint in the serving code:",{"type":15,"tag":51,"props":658,"children":661},{"code":659,"language":186,"meta":7,"className":660},"@app.get(\"\u002Fhealth\")\ndef health():\n    return {\"status\": \"ok\"}\n",[188],[662],{"type":15,"tag":56,"props":663,"children":664},{"__ignoreMap":7},[665],{"type":21,"value":659},{"type":15,"tag":23,"props":667,"children":668},{},[669],{"type":21,"value":670},"Kubernetes, ECS, or whatever orchestrator you use can hit this endpoint to know if the service is alive and ready.",{"type":15,"tag":34,"props":672,"children":674},{"id":673},"the-pattern",[675],{"type":21,"value":676},"The pattern",{"type":15,"tag":23,"props":678,"children":679},{},[680],{"type":21,"value":681},"All five of these problems have the same root cause: the notebook environment is forgiving in ways that production isn't. In a notebook, you're the only user, you control the input, you can see the output, and the environment is whatever happens to be installed.",{"type":15,"tag":23,"props":683,"children":684},{},[685],{"type":21,"value":686},"Production is the opposite. Multiple users, arbitrary input, invisible output, and a fixed environment that must be explicitly defined.",{"type":15,"tag":23,"props":688,"children":689},{},[690],{"type":21,"value":691},"The fixes aren't complicated. Pin dependencies, bundle preprocessing, validate input, add logging, and containerize. None of these require advanced tools or infrastructure — they're habits that pay off immediately.",{"type":15,"tag":693,"props":694,"children":695},"hr",{},[],{"type":15,"tag":23,"props":697,"children":698},{},[699,701,710,712,718],{"type":21,"value":700},"Moving models from notebook to production is exactly what ",{"type":15,"tag":702,"props":703,"children":707},"a",{"href":704,"rel":705},"https:\u002F\u002Fdeploying.ai",[706],"nofollow",[708],{"type":21,"value":709},"deploying.ai",{"type":21,"value":711}," helps teams do. If you're hitting these problems (or want to avoid them), ",{"type":15,"tag":702,"props":713,"children":715},{"href":714},"mailto:vlad@deploying.ai",[716],{"type":21,"value":717},"let's talk",{"type":21,"value":108},{"title":7,"searchDepth":720,"depth":720,"links":721},2,[722,726,729,732,735,738],{"id":36,"depth":720,"text":39,"children":723},[724],{"id":76,"depth":725,"text":79},3,{"id":174,"depth":720,"text":177,"children":727},[728],{"id":258,"depth":725,"text":79},{"id":311,"depth":720,"text":314,"children":730},[731],{"id":378,"depth":725,"text":79},{"id":416,"depth":720,"text":419,"children":733},[734],{"id":475,"depth":725,"text":79},{"id":513,"depth":720,"text":516,"children":736},[737],{"id":545,"depth":725,"text":79},{"id":673,"depth":720,"text":676},"markdown","content:articles:five-things-break-notebook-to-production.md","content","articles\u002Ffive-things-break-notebook-to-production.md","articles\u002Ffive-things-break-notebook-to-production","md",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"body":746,"_type":739,"_id":740,"_source":741,"_file":742,"_stem":743,"_extension":744},{"type":12,"children":747,"toc":1295},[748,752,756,760,764,768,772,779,789,793,815,823,839,847,863,867,871,879,889,893,926,930,940,948,964,968,972,976,980,1021,1025,1029,1037,1045,1049,1053,1057,1061,1065,1100,1104,1108,1116,1120,1128,1132,1136,1152,1156,1160,1170,1178,1182,1241,1245,1249,1257,1261,1265,1269,1273,1277,1280],{"type":15,"tag":16,"props":749,"children":750},{"id":18},[751],{"type":21,"value":8},{"type":15,"tag":23,"props":753,"children":754},{},[755],{"type":21,"value":27},{"type":15,"tag":23,"props":757,"children":758},{},[759],{"type":21,"value":32},{"type":15,"tag":34,"props":761,"children":762},{"id":36},[763],{"type":21,"value":39},{"type":15,"tag":23,"props":765,"children":766},{},[767],{"type":21,"value":44},{"type":15,"tag":23,"props":769,"children":770},{},[771],{"type":21,"value":49},{"type":15,"tag":51,"props":773,"children":774},{"code":53},[775],{"type":15,"tag":56,"props":776,"children":777},{"__ignoreMap":7},[778],{"type":21,"value":53},{"type":15,"tag":23,"props":780,"children":781},{},[782,783,788],{"type":21,"value":64},{"type":15,"tag":56,"props":784,"children":786},{"className":785},[],[787],{"type":21,"value":70},{"type":21,"value":72},{"type":15,"tag":74,"props":790,"children":791},{"id":76},[792],{"type":21,"value":79},{"type":15,"tag":23,"props":794,"children":795},{},[796,797,802,803,808,809,814],{"type":21,"value":84},{"type":15,"tag":56,"props":798,"children":800},{"className":799},[],[801],{"type":21,"value":90},{"type":21,"value":92},{"type":15,"tag":56,"props":804,"children":806},{"className":805},[],[807],{"type":21,"value":98},{"type":21,"value":100},{"type":15,"tag":56,"props":810,"children":812},{"className":811},[],[813],{"type":21,"value":106},{"type":21,"value":108},{"type":15,"tag":51,"props":816,"children":818},{"code":111,"language":112,"meta":7,"className":817},[114],[819],{"type":15,"tag":56,"props":820,"children":821},{"__ignoreMap":7},[822],{"type":21,"value":111},{"type":15,"tag":23,"props":824,"children":825},{},[826,827,832,833,838],{"type":21,"value":124},{"type":15,"tag":56,"props":828,"children":830},{"className":829},[],[831],{"type":21,"value":130},{"type":21,"value":132},{"type":15,"tag":56,"props":834,"children":836},{"className":835},[],[837],{"type":21,"value":106},{"type":21,"value":139},{"type":15,"tag":51,"props":840,"children":842},{"code":142,"language":143,"meta":7,"className":841},[145],[843],{"type":15,"tag":56,"props":844,"children":845},{"__ignoreMap":7},[846],{"type":21,"value":142},{"type":15,"tag":23,"props":848,"children":849},{},[850,851,856,857,862],{"type":21,"value":155},{"type":15,"tag":56,"props":852,"children":854},{"className":853},[],[855],{"type":21,"value":161},{"type":21,"value":163},{"type":15,"tag":56,"props":858,"children":860},{"className":859},[],[861],{"type":21,"value":169},{"type":21,"value":171},{"type":15,"tag":34,"props":864,"children":865},{"id":174},[866],{"type":21,"value":177},{"type":15,"tag":23,"props":868,"children":869},{},[870],{"type":21,"value":182},{"type":15,"tag":51,"props":872,"children":874},{"code":185,"language":186,"meta":7,"className":873},[188],[875],{"type":15,"tag":56,"props":876,"children":877},{"__ignoreMap":7},[878],{"type":21,"value":185},{"type":15,"tag":23,"props":880,"children":881},{},[882,883,888],{"type":21,"value":198},{"type":15,"tag":56,"props":884,"children":886},{"className":885},[],[887],{"type":21,"value":204},{"type":21,"value":206},{"type":15,"tag":23,"props":890,"children":891},{},[892],{"type":21,"value":211},{"type":15,"tag":213,"props":894,"children":895},{},[896,904,918],{"type":15,"tag":217,"props":897,"children":898},{},[899,903],{"type":15,"tag":221,"props":900,"children":901},{},[902],{"type":21,"value":225},{"type":21,"value":227},{"type":15,"tag":217,"props":905,"children":906},{},[907,911,912,917],{"type":15,"tag":221,"props":908,"children":909},{},[910],{"type":21,"value":235},{"type":21,"value":237},{"type":15,"tag":56,"props":913,"children":915},{"className":914},[],[916],{"type":21,"value":243},{"type":21,"value":245},{"type":15,"tag":217,"props":919,"children":920},{},[921,925],{"type":15,"tag":221,"props":922,"children":923},{},[924],{"type":21,"value":253},{"type":21,"value":255},{"type":15,"tag":74,"props":927,"children":928},{"id":258},[929],{"type":21,"value":79},{"type":15,"tag":23,"props":931,"children":932},{},[933,934,939],{"type":21,"value":265},{"type":15,"tag":56,"props":935,"children":937},{"className":936},[],[938],{"type":21,"value":271},{"type":21,"value":273},{"type":15,"tag":51,"props":941,"children":943},{"code":276,"language":186,"meta":7,"className":942},[188],[944],{"type":15,"tag":56,"props":945,"children":946},{"__ignoreMap":7},[947],{"type":21,"value":276},{"type":15,"tag":23,"props":949,"children":950},{},[951,952,957,958,963],{"type":21,"value":287},{"type":15,"tag":56,"props":953,"children":955},{"className":954},[],[956],{"type":21,"value":293},{"type":21,"value":295},{"type":15,"tag":56,"props":959,"children":961},{"className":960},[],[962],{"type":21,"value":301},{"type":21,"value":303},{"type":15,"tag":23,"props":965,"children":966},{},[967],{"type":21,"value":308},{"type":15,"tag":34,"props":969,"children":970},{"id":311},[971],{"type":21,"value":314},{"type":15,"tag":23,"props":973,"children":974},{},[975],{"type":21,"value":319},{"type":15,"tag":23,"props":977,"children":978},{},[979],{"type":21,"value":324},{"type":15,"tag":213,"props":981,"children":982},{},[983,991,999,1007],{"type":15,"tag":217,"props":984,"children":985},{},[986,990],{"type":15,"tag":221,"props":987,"children":988},{},[989],{"type":21,"value":335},{"type":21,"value":337},{"type":15,"tag":217,"props":992,"children":993},{},[994,998],{"type":15,"tag":221,"props":995,"children":996},{},[997],{"type":21,"value":345},{"type":21,"value":347},{"type":15,"tag":217,"props":1000,"children":1001},{},[1002,1006],{"type":15,"tag":221,"props":1003,"children":1004},{},[1005],{"type":21,"value":355},{"type":21,"value":357},{"type":15,"tag":217,"props":1008,"children":1009},{},[1010,1014,1015,1020],{"type":15,"tag":221,"props":1011,"children":1012},{},[1013],{"type":21,"value":365},{"type":21,"value":367},{"type":15,"tag":56,"props":1016,"children":1018},{"className":1017},[],[1019],{"type":21,"value":373},{"type":21,"value":375},{"type":15,"tag":74,"props":1022,"children":1023},{"id":378},[1024],{"type":21,"value":79},{"type":15,"tag":23,"props":1026,"children":1027},{},[1028],{"type":21,"value":385},{"type":15,"tag":51,"props":1030,"children":1032},{"code":388,"language":186,"meta":7,"className":1031},[188],[1033],{"type":15,"tag":56,"props":1034,"children":1035},{"__ignoreMap":7},[1036],{"type":21,"value":388},{"type":15,"tag":51,"props":1038,"children":1040},{"code":397,"language":186,"meta":7,"className":1039},[188],[1041],{"type":15,"tag":56,"props":1042,"children":1043},{"__ignoreMap":7},[1044],{"type":21,"value":397},{"type":15,"tag":23,"props":1046,"children":1047},{},[1048],{"type":21,"value":408},{"type":15,"tag":23,"props":1050,"children":1051},{},[1052],{"type":21,"value":413},{"type":15,"tag":34,"props":1054,"children":1055},{"id":416},[1056],{"type":21,"value":419},{"type":15,"tag":23,"props":1058,"children":1059},{},[1060],{"type":21,"value":424},{"type":15,"tag":23,"props":1062,"children":1063},{},[1064],{"type":21,"value":429},{"type":15,"tag":213,"props":1066,"children":1067},{},[1068,1076,1084,1092],{"type":15,"tag":217,"props":1069,"children":1070},{},[1071,1075],{"type":15,"tag":221,"props":1072,"children":1073},{},[1074],{"type":21,"value":440},{"type":21,"value":442},{"type":15,"tag":217,"props":1077,"children":1078},{},[1079,1083],{"type":15,"tag":221,"props":1080,"children":1081},{},[1082],{"type":21,"value":450},{"type":21,"value":452},{"type":15,"tag":217,"props":1085,"children":1086},{},[1087,1091],{"type":15,"tag":221,"props":1088,"children":1089},{},[1090],{"type":21,"value":460},{"type":21,"value":462},{"type":15,"tag":217,"props":1093,"children":1094},{},[1095,1099],{"type":15,"tag":221,"props":1096,"children":1097},{},[1098],{"type":21,"value":470},{"type":21,"value":472},{"type":15,"tag":74,"props":1101,"children":1102},{"id":475},[1103],{"type":21,"value":79},{"type":15,"tag":23,"props":1105,"children":1106},{},[1107],{"type":21,"value":482},{"type":15,"tag":51,"props":1109,"children":1111},{"code":485,"language":186,"meta":7,"className":1110},[188],[1112],{"type":15,"tag":56,"props":1113,"children":1114},{"__ignoreMap":7},[1115],{"type":21,"value":485},{"type":15,"tag":23,"props":1117,"children":1118},{},[1119],{"type":21,"value":496},{"type":15,"tag":51,"props":1121,"children":1123},{"code":499,"language":186,"meta":7,"className":1122},[188],[1124],{"type":15,"tag":56,"props":1125,"children":1126},{"__ignoreMap":7},[1127],{"type":21,"value":499},{"type":15,"tag":23,"props":1129,"children":1130},{},[1131],{"type":21,"value":510},{"type":15,"tag":34,"props":1133,"children":1134},{"id":513},[1135],{"type":21,"value":516},{"type":15,"tag":23,"props":1137,"children":1138},{},[1139,1140,1145,1146,1151],{"type":21,"value":521},{"type":15,"tag":56,"props":1141,"children":1143},{"className":1142},[],[1144],{"type":21,"value":527},{"type":21,"value":529},{"type":15,"tag":56,"props":1147,"children":1149},{"className":1148},[],[1150],{"type":21,"value":535},{"type":21,"value":537},{"type":15,"tag":23,"props":1153,"children":1154},{},[1155],{"type":21,"value":542},{"type":15,"tag":74,"props":1157,"children":1158},{"id":545},[1159],{"type":21,"value":79},{"type":15,"tag":23,"props":1161,"children":1162},{},[1163,1164,1169],{"type":21,"value":552},{"type":15,"tag":56,"props":1165,"children":1167},{"className":1166},[],[1168],{"type":21,"value":558},{"type":21,"value":560},{"type":15,"tag":51,"props":1171,"children":1173},{"code":563,"language":143,"meta":7,"className":1172},[145],[1174],{"type":15,"tag":56,"props":1175,"children":1176},{"__ignoreMap":7},[1177],{"type":21,"value":563},{"type":15,"tag":23,"props":1179,"children":1180},{},[1181],{"type":21,"value":574},{"type":15,"tag":213,"props":1183,"children":1184},{},[1185,1193,1206,1220,1228],{"type":15,"tag":217,"props":1186,"children":1187},{},[1188,1192],{"type":15,"tag":221,"props":1189,"children":1190},{},[1191],{"type":21,"value":585},{"type":21,"value":587},{"type":15,"tag":217,"props":1194,"children":1195},{},[1196,1200,1201],{"type":15,"tag":221,"props":1197,"children":1198},{},[1199],{"type":21,"value":595},{"type":21,"value":597},{"type":15,"tag":56,"props":1202,"children":1204},{"className":1203},[],[1205],{"type":21,"value":169},{"type":15,"tag":217,"props":1207,"children":1208},{},[1209,1213,1214,1219],{"type":15,"tag":221,"props":1210,"children":1211},{},[1212],{"type":21,"value":610},{"type":21,"value":612},{"type":15,"tag":56,"props":1215,"children":1217},{"className":1216},[],[1218],{"type":21,"value":618},{"type":21,"value":620},{"type":15,"tag":217,"props":1221,"children":1222},{},[1223,1227],{"type":15,"tag":221,"props":1224,"children":1225},{},[1226],{"type":21,"value":628},{"type":21,"value":630},{"type":15,"tag":217,"props":1229,"children":1230},{},[1231,1235,1236],{"type":15,"tag":221,"props":1232,"children":1233},{},[1234],{"type":21,"value":638},{"type":21,"value":640},{"type":15,"tag":56,"props":1237,"children":1239},{"className":1238},[],[1240],{"type":21,"value":646},{"type":15,"tag":23,"props":1242,"children":1243},{},[1244],{"type":21,"value":651},{"type":15,"tag":23,"props":1246,"children":1247},{},[1248],{"type":21,"value":656},{"type":15,"tag":51,"props":1250,"children":1252},{"code":659,"language":186,"meta":7,"className":1251},[188],[1253],{"type":15,"tag":56,"props":1254,"children":1255},{"__ignoreMap":7},[1256],{"type":21,"value":659},{"type":15,"tag":23,"props":1258,"children":1259},{},[1260],{"type":21,"value":670},{"type":15,"tag":34,"props":1262,"children":1263},{"id":673},[1264],{"type":21,"value":676},{"type":15,"tag":23,"props":1266,"children":1267},{},[1268],{"type":21,"value":681},{"type":15,"tag":23,"props":1270,"children":1271},{},[1272],{"type":21,"value":686},{"type":15,"tag":23,"props":1274,"children":1275},{},[1276],{"type":21,"value":691},{"type":15,"tag":693,"props":1278,"children":1279},{},[],{"type":15,"tag":23,"props":1281,"children":1282},{},[1283,1284,1289,1290,1294],{"type":21,"value":700},{"type":15,"tag":702,"props":1285,"children":1287},{"href":704,"rel":1286},[706],[1288],{"type":21,"value":709},{"type":21,"value":711},{"type":15,"tag":702,"props":1291,"children":1292},{"href":714},[1293],{"type":21,"value":717},{"type":21,"value":108},{"title":7,"searchDepth":720,"depth":720,"links":1296},[1297,1300,1303,1306,1309,1312],{"id":36,"depth":720,"text":39,"children":1298},[1299],{"id":76,"depth":725,"text":79},{"id":174,"depth":720,"text":177,"children":1301},[1302],{"id":258,"depth":725,"text":79},{"id":311,"depth":720,"text":314,"children":1304},[1305],{"id":378,"depth":725,"text":79},{"id":416,"depth":720,"text":419,"children":1307},[1308],{"id":475,"depth":725,"text":79},{"id":513,"depth":720,"text":516,"children":1310},[1311],{"id":545,"depth":725,"text":79},{"id":673,"depth":720,"text":676},1785232227842]