{"id":80,"date":"2025-12-20T06:56:33","date_gmt":"2025-12-20T06:56:33","guid":{"rendered":"https:\/\/steadyrabbit.in\/blogs\/?p=80"},"modified":"2025-12-20T06:56:33","modified_gmt":"2025-12-20T06:56:33","slug":"defeat-drift-synthetic-shadow-traffic-real-time-alerting-in-30-minutes","status":"publish","type":"post","link":"https:\/\/steadyrabbit.in\/blogs\/defeat-drift-synthetic-shadow-traffic-real-time-alerting-in-30-minutes\/","title":{"rendered":"Defeat Drift: Synthetic Shadow Traffic &amp; Real-Time Alerting in 30 Minutes"},"content":{"rendered":"\n<h4 class=\"wp-block-heading\">TL;DR (~90 w)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Waiting for AUC to nosedive is like noticing a flat tyre after the rim sparks. We\u2019ll build a <strong>30-minute drop-in drift-detection stack<\/strong>:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Synthetic shadow traffic<\/strong> &#8211; clones 1\u20135 % of production requests to a \u201cshadow\u201d model.<br><\/li>\n\n\n\n<li><strong>Real-time drift probes<\/strong> &#8211; population-stability-index (PSI) &amp; Jensen-Shannon divergence pushed to Prometheus.<br><\/li>\n\n\n\n<li><strong>Loki + Grafana alerts<\/strong> &#8211; Slack ping when PSI > 0.2 for 5 min or latency spikes.<br><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Copy-paste Docker Compose, Prometheus rules, and Grafana JSON dashboards included. Works with AWS SageMaker, Vertex AI, or on-prem KFServing.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Why Drift Kills Startups\u00a0<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Concept<\/em>: <strong>Data drift<\/strong> = feature distribution shifts; <strong>concept drift<\/strong> = relationship between X and y changes.<br><em>Impact<\/em>: credit denials, ad-spend waste, mis-diagnoses. FinTech client lost $70 k in one day when Covid-era outliers smashed its scoring model\u2014alert fired 12 hours late.<strong>Goal<\/strong>: Detect drift within <strong>5 minutes<\/strong> of pattern change, auto-route traffic to safe model, and start retraining.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Architecture at a Glance\u00a0<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">pgsql<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Client \u2192 API Gateway<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\u251c\u2500\u2500 95 %&nbsp; \u2192&nbsp; Prod Model (v2)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\u2514\u2500\u2500 5 % &nbsp; \u2192&nbsp; Shadow Model (v1)&nbsp;&nbsp;&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\u2514\u2500\u2500 Inference-Logger (Fluent Bit)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\u2514\u2500\u2192 Loki<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Prometheus \u2190&#8212; Drift-Exporter&nbsp; \u2190-\u2500 Shadow &amp; Prod logs<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\u2514\u2500 PSI, JS div, latency<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Grafana&nbsp; \u2190&#8212; Prometheus<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Slack Alert \u2190&#8211; Prom Alert-manager<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Shadow traffic<\/strong>: canary copies query <strong>after<\/strong> auth; no double-billing for LLM tokens if embedding cache used.<br><\/li>\n\n\n\n<li><strong>Drift-Exporter<\/strong>: Golang sidecar computing PSI &amp; JS divergence on sliding window (1 000 requests).<br><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Prometheus + Alertmanager<\/strong>: threshold rules; Grafana dashboard for trending.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Cloning Requests (Synthetic Shadow 1 %-5 %)\u00a0<\/h4>\n\n\n\n<h5 class=\"wp-block-heading\">3.1 AWS Lambda@Edge Example<\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">function handler(event) {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;const req = event.request;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;const rand = Math.random();<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;if (rand &lt; 0.05) { \/\/ 5 % shadow<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;req.headers[&#8216;x-shadow&#8217;] = [{ key: &#8216;x-shadow&#8217;, value: &#8216;true&#8217; }];<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;return req;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Downstream Nginx splits:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">nginx<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">map $http_x_shadow $shadow {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;default &nbsp; &nbsp; &nbsp; 0;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&#8220;true&#8221;&nbsp; &nbsp; &nbsp; &nbsp; 1;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">upstream prod &nbsp; { server model-v2:8080; }<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">upstream shadow { server model-v1:8080; }<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">server {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;location \/infer {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;if ($shadow) {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_pass http:\/\/shadow;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;proxy_pass http:\/\/prod;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">}<br><em>Latency overhead<\/em>: &lt; 2 ms because shadow response is <em>fire-and-forget<\/em> (async).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Drift-Exporter Sidecar\u00a0<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Dockerfile<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">dockerfile<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">FROM golang:1.22-alpine<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">WORKDIR \/app<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">COPY . .<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">RUN go build -o drift-exporter .<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CMD [&#8220;.\/drift-exporter&#8221;]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Core logic:<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">go<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">for req := range kafkaConsumer {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;feats := extractFeatures(req)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;prodVec.Observe(feats)&nbsp; &nbsp; \/\/ ring buffer 1 000<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;shadowVec.Observe(feats)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;if prodVec.Len() == 1000 {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;psi := calcPSI(prodVec, shadowVec)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;js&nbsp; := calcJSDiv(prodVec, shadowVec)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;promPSI.Set(psi)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;promJS.Set(js)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prodVec.Reset(); shadowVec.Reset()<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Exports psi and js_divergence gauges on \/metrics.<strong>PSI calculation<\/strong>: 10 equal-width bins; alert when PSI &gt; 0.2.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Prometheus Alert Rules\u00a0<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">drift_alerts.yml<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">yaml<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">groups:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; name: drift<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;rules:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&#8211; alert: FeaturePSIHigh<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;expr: psi &gt; 0.2<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;for: 5m<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;labels:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;severity: warning<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;annotations:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;summary: &#8220;Feature drift PSI {{ $value }}&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description: |<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PSI exceeded 0.2 for 5 minutes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Check retraining pipeline.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&#8211; alert: LatencySpike<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;expr: histogram_quantile(0.95, sum(rate(inference_latency_bucket[5m])) by (le)) &gt; 500<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;for: 3m<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;labels:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;severity: critical<br>Alertmanager route \u2192 Slack #mlops.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Grafana Dashboard Highlights\u00a0<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Panels:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>PSI gauge<\/strong> (red > 0.2).<br><\/li>\n\n\n\n<li><strong>JS divergence heatmap<\/strong> per feature.<br><\/li>\n\n\n\n<li><strong>Latency p95<\/strong> overlay prod vs shadow.<br><\/li>\n\n\n\n<li><strong>Traffic split<\/strong> (% shadow).<br><\/li>\n\n\n\n<li><strong>Auto-rollback toggle<\/strong> (Alertmanager webhook\u2192 Terraform Cloud run).<br><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Full JSON available in repo grafana\/drift_dashboard.json.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Auto-Rollback Strategy\u00a0<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Alertmanager \u2192 Webhook Lambda:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">python<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">if alert[&#8216;labels&#8217;][&#8216;severity&#8217;] == &#8216;critical&#8217;:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;ssm.put_parameter(Name=&#8221;\/model\/current&#8221;, Value=&#8221;v1&#8243;, Overwrite=True)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nginx watches SSM Parameter Store via sidecar; flips traffic 100 % back to stable v1 within 90 s.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Rollback tests:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Inject synthetic drift (psi = 0.35).<br><\/li>\n\n\n\n<li>Alert fired in 2 m 40 s.<br><\/li>\n\n\n\n<li>Traffic shifted; p95 latency recovered from 530 ms \u2192 210 ms<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Time &amp; Cost Benchmarks\u00a0<\/h4>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Component<\/strong><\/td><td><strong>Extra Latency<\/strong><\/td><td><strong>Cost \/1 M req<\/strong><\/td><\/tr><tr><td>Shadow clone<\/td><td>+2 ms<\/td><td>+$0.15 (extra model calls)<\/td><\/tr><tr><td>Drift-Exporter CPU<\/td><td>N\/A<\/td><td>$0.03<\/td><\/tr><tr><td>Prom\/Loki\/Grafana<\/td><td>N\/A<\/td><td>$0.08<\/td><\/tr><tr><td><strong>Total<\/strong><\/td><td><strong>\u2248 +2 ms<\/strong><\/td><td><strong>$0.26<\/strong><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Less than 1 % of OpenAI token spend for same QPS.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Case Study \u2014 Social Commerce Wallet\u00a0<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Problem<\/em>: purchase-fraud model mis-fired after festival sale; false positives \u2191 70 %.<br><em>Solution<\/em>: implemented shadow v2 model + drift-exporter in 3 days.<br><em>Outcome<\/em>:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Metric<\/strong><\/td><td><strong>Before<\/strong><\/td><td><strong>After<\/strong><\/td><\/tr><tr><td>Manual review queue<\/td><td>18 k\/day<\/td><td>3 k\/day<\/td><\/tr><tr><td>PSI alert time<\/td><td>N\/A<\/td><td>4 m 20 s<\/td><\/tr><tr><td>Revenue loss<\/td><td>$9.2 k<\/td><td>$1.1 k<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Saved $8 k\/day during festive surge.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Pitfalls &amp; Pro Tips\u00a0<\/h4>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Pitfall<\/strong><\/td><td><strong>Fix<\/strong><\/td><\/tr><tr><td>Shadow model costs doubling tokens<\/td><td>Use <em>log-only<\/em> shadow for LLMs\u2014skip generation.<\/td><\/tr><tr><td>Mixed tenant data corrupting drift signal<\/td><td>Compute PSI per tenant; Alert only if three tenants red.<\/td><\/tr><tr><td>Loki disk bloat<\/td><td>30-day retention on shadow label; prod kept 90 days.<\/td><\/tr><tr><td>False positives on low-traffic night hours<\/td><td>for: 5m + condition psi &gt; 0.2 and requests &gt; 100.<\/td><\/tr><tr><td>Hashing PII before logs<\/td><td>Use SHA-256; comply with redaction guide from Post #3.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Adoption Roadmap\u00a0<\/h4>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>Sprint<\/strong><\/td><td><strong>Milestone<\/strong><\/td><\/tr><tr><td>1<\/td><td>Deploy drift-exporter sidecar &amp; expose Prom metrics<\/td><\/tr><tr><td>2<\/td><td>Clone 1 % shadow traffic; Grafana dashboard live<\/td><\/tr><tr><td>3<\/td><td>Slack alerts + manual rollback runbook<\/td><\/tr><tr><td>4<\/td><td>Auto-rollback via SSM or Terraform Cloud<\/td><\/tr><tr><td>5<\/td><td>Expand to multi-feature PSI &amp; tenant segmentation<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Take-Home Checklist\u00a0<\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Clone 1\u20135 % of traffic to shadow model.<br><\/li>\n\n\n\n<li>Drop drift-exporter sidecar; emit PSI &amp; JS divergence every 1 000 req.<br><\/li>\n\n\n\n<li>Alert when PSI > 0.2 for 5 min.<br><\/li>\n\n\n\n<li>Auto-rollback via feature flag or endpoint switch.<br><\/li>\n\n\n\n<li>Review Grafana dashboard weekly; schedule retrain on amber trend.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>TL;DR (~90 w) Waiting for AUC to nosedive is like noticing a flat tyre after the rim sparks. We\u2019ll build a 30-minute drop-in drift-detection stack: Copy-paste Docker Compose, Prometheus rules, and Grafana JSON dashboards included. Works with AWS SageMaker, Vertex AI, or on-prem KFServing. Why Drift Kills Startups\u00a0 Concept: Data drift = feature distribution shifts; [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":20,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-80","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-ml-best-practices"],"_links":{"self":[{"href":"https:\/\/steadyrabbit.in\/blogs\/wp-json\/wp\/v2\/posts\/80","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/steadyrabbit.in\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/steadyrabbit.in\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/steadyrabbit.in\/blogs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/steadyrabbit.in\/blogs\/wp-json\/wp\/v2\/comments?post=80"}],"version-history":[{"count":1,"href":"https:\/\/steadyrabbit.in\/blogs\/wp-json\/wp\/v2\/posts\/80\/revisions"}],"predecessor-version":[{"id":81,"href":"https:\/\/steadyrabbit.in\/blogs\/wp-json\/wp\/v2\/posts\/80\/revisions\/81"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/steadyrabbit.in\/blogs\/wp-json\/wp\/v2\/media\/20"}],"wp:attachment":[{"href":"https:\/\/steadyrabbit.in\/blogs\/wp-json\/wp\/v2\/media?parent=80"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/steadyrabbit.in\/blogs\/wp-json\/wp\/v2\/categories?post=80"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/steadyrabbit.in\/blogs\/wp-json\/wp\/v2\/tags?post=80"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}