{"id":81,"date":"2025-06-09T22:50:00","date_gmt":"2025-06-09T22:50:00","guid":{"rendered":"https:\/\/wordpress.joeltan.me\/?p=81"},"modified":"2026-01-26T11:27:24","modified_gmt":"2026-01-26T11:27:24","slug":"from-pandas-to-the-cloud-how-i-accidentally-became-a-container-evangelist","status":"publish","type":"post","link":"https:\/\/joeltan.me\/?p=81","title":{"rendered":"From Pandas to the Cloud: How I Accidentally Became a Container Evangelist"},"content":{"rendered":"\n<p>A few months ago, I was minding my own business\u2014tuning data pipelines, optimizing our queries, and doing the usual data engineering work\u2014when a curious message popped up on Teams.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u201cHey, got a sec? We\u2019ve got this demand forecasting script that\u2019s&#8230; uh, getting out of hand. Can you take a look?\u201d<\/p>\n<\/blockquote>\n\n\n\n<p>Sure, why not?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Forecasting Fiasco<\/h3>\n\n\n\n<p>The business team had been running their demand forecasting using a familiar tool\u2014Pandas. It wasn\u2019t flashy, but it worked. Well, sort of. The process pulled source data from multiple systems: CRM, Budgeting, Revenue and even a few Excel files manually emailed every week.<\/p>\n\n\n\n<p>The pipeline (if you could call it that) involved:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Opening the python project on someone\u2019s personal laptop<\/li>\n\n\n\n<li>Running the main script<\/li>\n\n\n\n<li>Exporting results to CSVs<\/li>\n\n\n\n<li>Manually uploading those files to an Azure Storage container<\/li>\n\n\n\n<li>Then, pray that the files are uploaded successfully to the database, which occasionally failed due to formatting issues.<\/li>\n<\/ul>\n\n\n\n<p>It was equal parts art, science, and daily anxiety.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Whose Turn Is It to Run the Forecast<\/h3>\n\n\n\n<p>The script wasn\u2019t running on any server. It was tied\u2014rather tragically\u2014to whoever available to run it. Every week, a different analyst would try to run it.<\/p>\n\n\n\n<p>I still remember the call I got one morning:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u201cHey, I tried running the forecast and it\u2019s throwing a weird error about <code>openpyxl<\/code> and <code>pyodbc<\/code>. I don\u2019t know what that means.\u201d<\/p>\n<\/blockquote>\n\n\n\n<p>I did. It meant someone\u2019s Conda environment had gone rogue.<\/p>\n\n\n\n<p>The business wasn\u2019t just running forecasts. They were wrestling Conda environment, fighting PATH variables, and battling dependencies hell. It was a miracle anything worked at all.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Enter the Data Engineer<\/h3>\n\n\n\n<p>That\u2019s when they came to me.<\/p>\n\n\n\n<p>The request was simple enough: <em>\u201cCan we automate this?\u201d<\/em><\/p>\n\n\n\n<p>So I started looking at options:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Azure Synapse Notebook? Tempting, but the script was packed with custom Python libraries, written using Python 3.7 that will not be compatible with the supported Synapse Spark 3.5 runtime.<\/li>\n\n\n\n<li>Azure Data Factory? Also an option, but converting a sprawling Pandas script into ADF data flows felt like translating poetry into assembly language.<\/li>\n<\/ul>\n\n\n\n<p>After a few trials, I realized something important: <strong>we didn\u2019t need to rewrite the logic<\/strong>\u2014we just needed to <strong>containerize it<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A Job for Azure Container Jobs<\/h3>\n\n\n\n<p>And that\u2019s when I discovered <strong>Azure Container Jobs<\/strong>.<\/p>\n\n\n\n<p>No need for orchestration engines, no Kubernetes cluster to maintain, and no VM just sitting idle. I could:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Containerize the Python application into a <strong>Docker container<\/strong><\/li>\n\n\n\n<li>Push it to <strong>Azure Container Registry<\/strong><\/li>\n\n\n\n<li>Set up a <strong>Azure Container Apps Environment<\/strong><\/li>\n\n\n\n<li>Create an<strong> Azure File Share<\/strong> and mount the volume in the container<\/li>\n\n\n\n<li><strong>Create a Container App Job<\/strong> and schedule it to run once a week (or whenever needed), <strong>persisting <\/strong>the forecasting report in Azure File Share<\/li>\n<\/ul>\n\n\n\n<p>Best of all? It <strong>ran the exact same environment<\/strong> every time. No more \u201cit works on my laptop\u201d debates. Here&#8217;s what the solution looks like.<\/p>\n\n\n\n<div class=\"wp-block-group has-white-background-color has-background\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/joeltan.me\/content\/images\/2025\/06\/azure-container-app.drawio.png\" alt=\"azure container app.drawio.png\"\/><\/figure>\n<\/div><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Dockerfile (Simplified)<\/h3>\n\n\n\n<p>To keep the size of the image down, I used a multi-stage build. This dramatically reduce the image size by 50%:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\n# Use the official Miniconda base image\nFROM mcr.microsoft.com\/devcontainers\/miniconda:latest AS build\n\n# Copy environment files\nCOPY environment.yml environment.yml\n\n# Install system dependencies\nRUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends \\\n    &amp;&amp; apt-get clean \\\n    &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/*\n\n# Create a default conda environment\nRUN conda env create -f environment.yml\n\n# Install conda-pack:\nRUN conda install -c conda-forge conda-pack\n\n# Use conda-pack to create a virtual env\nRUN conda-pack -n default -o \/local\/env.tar &amp;&amp; \\\n  mkdir \/venv &amp;&amp; cd \/venv &amp;&amp; tar xf \/local\/env.tar &amp;&amp; \\\n  rm \/local\/env.tar\n\n# This makes the entire \/venv directory truly self-contained and portable\nRUN \/venv\/bin\/conda-unpack\n\n# We starts brand new, from a minimal base image without conda\n# as the venv we built previously is completely self-sufficient\nFROM debian:buster AS runtime\n\n# Copy \/venv from the previous stage:\nCOPY --from=build \/venv \/venv\n\n# Add Conda Python to PATH\nENV PATH=&quot;\/venv\/bin:$PATH&quot;\n\n# Copy the main script\nCOPY forecasting_pipeline.py .\n\n# Default run command\nCMD &#x5B;&quot;python&quot;, &quot;forecasting_pipeline.py&quot;]\n\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Example environment.yml<\/h3>\n\n\n\n<p>The trickiest part of this exercise was upgrading Python from 3.7 to 3.11, but it turned out to be a blessing in disguise \u2014 the newer version brought noticeable performance improvements, better error messages, and long-term support, making our container builds leaner and our data pipeline faster and more maintainable.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\nname: default\nchannels:\n  - conda-forge\n  - defaults\ndependencies:\n  - python=3.11\n  - pandas\n  - numpy\n  - scipy\n  - plotly\n  - pyodbc\n  - azure-identity\n  - python-dateutil\n  - pip\n  - pip:\n    - python-dotenv\n    - sqlalchemy\n\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Container Registry and Deployment<\/h3>\n\n\n\n<p>To deploy:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\n# Build the container\ndocker build -t forecasting-pipeline .\n\n# Tag and push to ACR\naz acr login --name myregistry\ndocker tag forecasting-pipeline myregistry.azurecr.io\/forecasting-pipeline:latest\ndocker push myregistry.azurecr.io\/forecasting-pipeline:latest\n\n<\/pre><\/div>\n\n\n<p>Then, schedule using an Azure Container Job with the Azure File Share mounted and appropriate secrets\/environment variables passed in.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">From Chaos to Confidence<\/h3>\n\n\n\n<p>Now the forecasting pipeline runs like clockwork. The business team doesn\u2019t worry about conda environments or weird Excel edge cases. They just get their forecast files where they need them, when they need them.<\/p>\n\n\n\n<p>I didn\u2019t set out to become a DevOps-for-Pandas advocate. But sometimes the best solutions aren\u2019t the flashiest\u2014they\u2019re the ones that quietly work, week after week.<\/p>\n\n\n\n<p>And all it took was one container.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Epilogue: Lessons Learned<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Manual data pipelines are a hidden tax on productivity.<\/li>\n\n\n\n<li>Not everything needs to be rewritten\u2014encapsulation can be powerful.<\/li>\n\n\n\n<li>Azure Container Jobs are a sweet spot between DIY infrastructure and fully managed orchestration.<\/li>\n<\/ul>\n\n\n\n<p>If you\u2019re a data engineer caught between business logic and bad environments, don\u2019t overlook containers. Sometimes, all you need is a good Dockerfile and a quiet Sunday to set things right.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A few months ago, I was minding my own business\u2014tuning data pipelines, optimizing our queries, and doing the usual data&#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":83,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[3],"tags":[],"class_list":["post-81","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-data-engineering-systems-that-stay-up"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>From Pandas to the Cloud: How I Accidentally Became a Container Evangelist - Joel Tan Tech Blogs<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/joeltan.me\/?p=81\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"From Pandas to the Cloud: How I Accidentally Became a Container Evangelist - Joel Tan Tech Blogs\" \/>\n<meta property=\"og:description\" content=\"A few months ago, I was minding my own business\u2014tuning data pipelines, optimizing our queries, and doing the usual data&#046;&#046;&#046;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/joeltan.me\/?p=81\" \/>\n<meta property=\"og:site_name\" content=\"Joel Tan Tech Blogs\" \/>\n<meta property=\"article:published_time\" content=\"2025-06-09T22:50:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-01-26T11:27:24+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/joeltan.me\/wp-content\/uploads\/2026\/01\/a-spacious-interior-view-of-stockholm-public-library-showcasing-its-circular-design-and-bookshelves.-4318445-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1709\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Joel Tan\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Joel Tan\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/joeltan.me\/?p=81#article\",\"isPartOf\":{\"@id\":\"https:\/\/joeltan.me\/?p=81\"},\"author\":{\"name\":\"Joel Tan\",\"@id\":\"https:\/\/joeltan.me\/#\/schema\/person\/db13342201787db723bfdeadcd792743\"},\"headline\":\"From Pandas to the Cloud: How I Accidentally Became a Container Evangelist\",\"datePublished\":\"2025-06-09T22:50:00+00:00\",\"dateModified\":\"2026-01-26T11:27:24+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/joeltan.me\/?p=81\"},\"wordCount\":741,\"commentCount\":0,\"image\":{\"@id\":\"https:\/\/joeltan.me\/?p=81#primaryimage\"},\"thumbnailUrl\":\"https:\/\/joeltan.me\/wp-content\/uploads\/2026\/01\/a-spacious-interior-view-of-stockholm-public-library-showcasing-its-circular-design-and-bookshelves.-4318445-scaled.jpg\",\"articleSection\":[\"Data Engineering: Systems That Stay Up\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/joeltan.me\/?p=81#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/joeltan.me\/?p=81\",\"url\":\"https:\/\/joeltan.me\/?p=81\",\"name\":\"From Pandas to the Cloud: How I Accidentally Became a Container Evangelist - Joel Tan Tech Blogs\",\"isPartOf\":{\"@id\":\"https:\/\/joeltan.me\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/joeltan.me\/?p=81#primaryimage\"},\"image\":{\"@id\":\"https:\/\/joeltan.me\/?p=81#primaryimage\"},\"thumbnailUrl\":\"https:\/\/joeltan.me\/wp-content\/uploads\/2026\/01\/a-spacious-interior-view-of-stockholm-public-library-showcasing-its-circular-design-and-bookshelves.-4318445-scaled.jpg\",\"datePublished\":\"2025-06-09T22:50:00+00:00\",\"dateModified\":\"2026-01-26T11:27:24+00:00\",\"author\":{\"@id\":\"https:\/\/joeltan.me\/#\/schema\/person\/db13342201787db723bfdeadcd792743\"},\"breadcrumb\":{\"@id\":\"https:\/\/joeltan.me\/?p=81#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/joeltan.me\/?p=81\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/joeltan.me\/?p=81#primaryimage\",\"url\":\"https:\/\/joeltan.me\/wp-content\/uploads\/2026\/01\/a-spacious-interior-view-of-stockholm-public-library-showcasing-its-circular-design-and-bookshelves.-4318445-scaled.jpg\",\"contentUrl\":\"https:\/\/joeltan.me\/wp-content\/uploads\/2026\/01\/a-spacious-interior-view-of-stockholm-public-library-showcasing-its-circular-design-and-bookshelves.-4318445-scaled.jpg\",\"width\":2560,\"height\":1709,\"caption\":\"A spacious interior view of Stockholm Public Library, showcasing its circular design and bookshelves.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/joeltan.me\/?p=81#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/joeltan.me\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"From Pandas to the Cloud: How I Accidentally Became a Container Evangelist\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/joeltan.me\/#website\",\"url\":\"https:\/\/joeltan.me\/\",\"name\":\"Joel Tan Tech Blogs\",\"description\":\"Building systems that survive real life\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/joeltan.me\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/joeltan.me\/#\/schema\/person\/db13342201787db723bfdeadcd792743\",\"name\":\"Joel Tan\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/joeltan.me\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d9b5d1ab218cb2478280027d371ea60543f6551132d31a8cbd45a5a5b3fbadc9?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d9b5d1ab218cb2478280027d371ea60543f6551132d31a8cbd45a5a5b3fbadc9?s=96&d=mm&r=g\",\"caption\":\"Joel Tan\"},\"sameAs\":[\"http:\/\/192.168.1.146\"],\"url\":\"https:\/\/joeltan.me\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"From Pandas to the Cloud: How I Accidentally Became a Container Evangelist - Joel Tan Tech Blogs","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/joeltan.me\/?p=81","og_locale":"en_US","og_type":"article","og_title":"From Pandas to the Cloud: How I Accidentally Became a Container Evangelist - Joel Tan Tech Blogs","og_description":"A few months ago, I was minding my own business\u2014tuning data pipelines, optimizing our queries, and doing the usual data&#46;&#46;&#46;","og_url":"https:\/\/joeltan.me\/?p=81","og_site_name":"Joel Tan Tech Blogs","article_published_time":"2025-06-09T22:50:00+00:00","article_modified_time":"2026-01-26T11:27:24+00:00","og_image":[{"width":2560,"height":1709,"url":"https:\/\/joeltan.me\/wp-content\/uploads\/2026\/01\/a-spacious-interior-view-of-stockholm-public-library-showcasing-its-circular-design-and-bookshelves.-4318445-scaled.jpg","type":"image\/jpeg"}],"author":"Joel Tan","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Joel Tan","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/joeltan.me\/?p=81#article","isPartOf":{"@id":"https:\/\/joeltan.me\/?p=81"},"author":{"name":"Joel Tan","@id":"https:\/\/joeltan.me\/#\/schema\/person\/db13342201787db723bfdeadcd792743"},"headline":"From Pandas to the Cloud: How I Accidentally Became a Container Evangelist","datePublished":"2025-06-09T22:50:00+00:00","dateModified":"2026-01-26T11:27:24+00:00","mainEntityOfPage":{"@id":"https:\/\/joeltan.me\/?p=81"},"wordCount":741,"commentCount":0,"image":{"@id":"https:\/\/joeltan.me\/?p=81#primaryimage"},"thumbnailUrl":"https:\/\/joeltan.me\/wp-content\/uploads\/2026\/01\/a-spacious-interior-view-of-stockholm-public-library-showcasing-its-circular-design-and-bookshelves.-4318445-scaled.jpg","articleSection":["Data Engineering: Systems That Stay Up"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/joeltan.me\/?p=81#respond"]}]},{"@type":"WebPage","@id":"https:\/\/joeltan.me\/?p=81","url":"https:\/\/joeltan.me\/?p=81","name":"From Pandas to the Cloud: How I Accidentally Became a Container Evangelist - Joel Tan Tech Blogs","isPartOf":{"@id":"https:\/\/joeltan.me\/#website"},"primaryImageOfPage":{"@id":"https:\/\/joeltan.me\/?p=81#primaryimage"},"image":{"@id":"https:\/\/joeltan.me\/?p=81#primaryimage"},"thumbnailUrl":"https:\/\/joeltan.me\/wp-content\/uploads\/2026\/01\/a-spacious-interior-view-of-stockholm-public-library-showcasing-its-circular-design-and-bookshelves.-4318445-scaled.jpg","datePublished":"2025-06-09T22:50:00+00:00","dateModified":"2026-01-26T11:27:24+00:00","author":{"@id":"https:\/\/joeltan.me\/#\/schema\/person\/db13342201787db723bfdeadcd792743"},"breadcrumb":{"@id":"https:\/\/joeltan.me\/?p=81#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/joeltan.me\/?p=81"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/joeltan.me\/?p=81#primaryimage","url":"https:\/\/joeltan.me\/wp-content\/uploads\/2026\/01\/a-spacious-interior-view-of-stockholm-public-library-showcasing-its-circular-design-and-bookshelves.-4318445-scaled.jpg","contentUrl":"https:\/\/joeltan.me\/wp-content\/uploads\/2026\/01\/a-spacious-interior-view-of-stockholm-public-library-showcasing-its-circular-design-and-bookshelves.-4318445-scaled.jpg","width":2560,"height":1709,"caption":"A spacious interior view of Stockholm Public Library, showcasing its circular design and bookshelves."},{"@type":"BreadcrumbList","@id":"https:\/\/joeltan.me\/?p=81#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/joeltan.me\/"},{"@type":"ListItem","position":2,"name":"From Pandas to the Cloud: How I Accidentally Became a Container Evangelist"}]},{"@type":"WebSite","@id":"https:\/\/joeltan.me\/#website","url":"https:\/\/joeltan.me\/","name":"Joel Tan Tech Blogs","description":"Building systems that survive real life","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/joeltan.me\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/joeltan.me\/#\/schema\/person\/db13342201787db723bfdeadcd792743","name":"Joel Tan","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/joeltan.me\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d9b5d1ab218cb2478280027d371ea60543f6551132d31a8cbd45a5a5b3fbadc9?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d9b5d1ab218cb2478280027d371ea60543f6551132d31a8cbd45a5a5b3fbadc9?s=96&d=mm&r=g","caption":"Joel Tan"},"sameAs":["http:\/\/192.168.1.146"],"url":"https:\/\/joeltan.me\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/joeltan.me\/index.php?rest_route=\/wp\/v2\/posts\/81","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/joeltan.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/joeltan.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/joeltan.me\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/joeltan.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=81"}],"version-history":[{"count":2,"href":"https:\/\/joeltan.me\/index.php?rest_route=\/wp\/v2\/posts\/81\/revisions"}],"predecessor-version":[{"id":88,"href":"https:\/\/joeltan.me\/index.php?rest_route=\/wp\/v2\/posts\/81\/revisions\/88"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/joeltan.me\/index.php?rest_route=\/wp\/v2\/media\/83"}],"wp:attachment":[{"href":"https:\/\/joeltan.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=81"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/joeltan.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=81"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/joeltan.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=81"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}