<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shiv</title>
    <description>The latest articles on DEV Community by Shiv (@riqu).</description>
    <link>https://dev.to/riqu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2833287%2F37a91d06-ee35-4477-aca6-8d1bbf42a276.jpg</url>
      <title>DEV Community: Shiv</title>
      <link>https://dev.to/riqu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/riqu"/>
    <language>en</language>
    <item>
      <title>I got tired of upstreams. I built a kill switch - MockRelay</title>
      <dc:creator>Shiv</dc:creator>
      <pubDate>Tue, 18 Aug 2026 14:27:09 +0000</pubDate>
      <link>https://dev.to/riqu/i-got-tired-of-upstreams-i-built-a-kill-switch-mockrelay-3in3</link>
      <guid>https://dev.to/riqu/i-got-tired-of-upstreams-i-built-a-kill-switch-mockrelay-3in3</guid>
      <description>&lt;p&gt;&lt;strong&gt;Every sprint, the same story.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You need a specific test scenario — a cancelled policy, a flagged claim, an empty portfolio. You know exactly what the upstream response should look like. You've seen it in production. But you still have to raise a request with another team, wait for them to set it up, and hope it's still there when you come back.&lt;/p&gt;

&lt;p&gt;By the time it's ready, the sprint is half over. Or the environment is down. Or someone else's test has overwritten it.&lt;/p&gt;

&lt;p&gt;And on the bad days — the upstream itself goes down. One service, every team blocked.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Daily Blocker
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Upstream services are shared, unstable, and often unavailable in dev environments&lt;/li&gt;
&lt;li&gt;One service going down blocks ALL teams depending on it&lt;/li&gt;
&lt;li&gt;Test data is shared — one team's test corrupts another's&lt;/li&gt;
&lt;li&gt;Simulating edge cases (errors, empty states, specific values) requires real environment access&lt;/li&gt;
&lt;li&gt;Teams are blocked waiting for other teams to finish their APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Result: Slow development cycles, late integration bugs, expensive UAT defects.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Introducing MockRelay
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;MockRelay&lt;/strong&gt; is a transport-layer interception platform. It sits between your application and its upstream dependencies,&lt;br&gt;
intercepting every outgoing HTTP call — without touching a single line of your application code.&lt;/p&gt;

&lt;p&gt;One JAR dependency on your Spring Boot app. One npm import in your Angular app. That's the entire adoption cost.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intercepts outgoing HTTP calls without modifying a single line of application code&lt;/li&gt;
&lt;li&gt;Inject edge case scenarios — error codes, empty states, specific values — by directly editing the JSON in a dedicated UI&lt;/li&gt;
&lt;li&gt;Mode toggle: &lt;strong&gt;RECORD&lt;/strong&gt;→ &lt;strong&gt;REPLAY&lt;/strong&gt;→ &lt;strong&gt;PASSTHROUGH&lt;/strong&gt;— switch to real/mock data instantly. No redeployment, no config changes,
no restarts&lt;/li&gt;
&lt;li&gt;Teams define what their upstream responses should look like&lt;/li&gt;
&lt;li&gt;Framework serves controlled mock responses every time that endpoint is called&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbgapblbv5fi4ajrq1tas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbgapblbv5fi4ajrq1tas.png" alt=" " width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;▎ &lt;strong&gt;"Zero config. One click. Never blocked by an upstream again."&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Kill Switch
&lt;/h2&gt;

&lt;p&gt;Every service registered in MockRelay has three modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RECORD — real API calls pass through to the upstream and get captured&lt;/li&gt;
&lt;li&gt;REPLAY — interceptor serves mock data instead of hitting the upstream&lt;/li&gt;
&lt;li&gt;PASSTHROUGH — interceptor steps aside completely, real calls go through unmodified&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You switch between them from the UI. No redeployment. No config file changes. No restarts.&lt;/p&gt;

&lt;p&gt;Need to test an edge case — a cancelled policy, a zero-balance account, a 500 error? Edit the mock JSON directly in the UI, reload your app, and it's there. No ticket raised, no other team involved, no environment to coordinate.&lt;/p&gt;

&lt;p&gt;And if you ever need to verify against the real upstream — one click and you're on live data. One click back and you're on mock. It works in both directions, instantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Interface to manage services
&lt;/h2&gt;

&lt;p&gt;MockRelay ships with a management portal where every team can see their registered APIs, inspect and edit the generated mock JSON, configure rules, and toggle modes — all in one place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2hi0p8m0h67pq990ynjq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2hi0p8m0h67pq990ynjq.png" alt=" " width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Teams don't need to touch config files or coordinate with other teams. Each team owns their mock data source completely. I will share a different post continuing on the application flow.(Also, meanwhile I will work on making it a bit visually appealing :] )&lt;/p&gt;




&lt;h2&gt;
  
  
  Two Ways to Deploy
&lt;/h2&gt;

&lt;p&gt;This is the part most mocking tools miss.&lt;/p&gt;

&lt;p&gt;Level 1 — UI intercepts&lt;/p&gt;

&lt;p&gt;Angular UI → [npm interceptor] → Mock Data Service&lt;/p&gt;

&lt;p&gt;Fast isolated UI development. The frontend team gets unblocked immediately. Trade-off: backend orchestration is not tested, only the UI layer is validated against mock data.&lt;/p&gt;

&lt;p&gt;Level 2 — Backend intercepts&lt;/p&gt;

&lt;p&gt;Angular UI → Real Backend → [JAR interceptor] → Mock Data Service&lt;/p&gt;

&lt;p&gt;The backend does real orchestration against mock upstream data. The UI receives a real backend response. Only the upstream dependency is mocked — everything else runs as it would in production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcx1jfcpsvjwhph1gzbxl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcx1jfcpsvjwhph1gzbxl.png" alt=" " width="799" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Level 2 is where MockRelay gets powerful. Your integration is fully tested. The only thing that isn't real is the upstream you don't control.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Mock Data Is Generated
&lt;/h2&gt;

&lt;p&gt;MockRelay doesn't serve static JSON files. It generates mock data through a three-pass rule engine.&lt;/p&gt;

&lt;p&gt;Pass 1 — Auto-randomize&lt;br&gt;
Every field is randomized based on type keywords and field name heuristics. A field named policyId gets a UUID. A field named creationDate gets an ISO timestamp. No configuration needed.&lt;/p&gt;

&lt;p&gt;Pass 2 — Apply Rules&lt;br&gt;
User-defined rules override specific fields. Five rule types are supported:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnn3zvtlebx47d3ry2zk9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnn3zvtlebx47d3ry2zk9.png" alt=" " width="775" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Only pin what matters. Everything else auto-randomizes.&lt;/p&gt;

&lt;p&gt;Pass 3 — Business Rules&lt;br&gt;
Conditional logic applied last. Written in plain English:&lt;/p&gt;

&lt;p&gt;if status == CANCELLED then refundAmount = 0&lt;br&gt;
  if policyType == COMMERCIAL then premium &amp;gt; 10000&lt;/p&gt;

&lt;p&gt;Rules persist permanently. Generated mock data expires in 7 days and gets regenerated on demand.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Your Schema In
&lt;/h2&gt;

&lt;p&gt;MockRelay supports three ways to define what your upstream response looks like:&lt;/p&gt;

&lt;p&gt;Swagger import — point it at a Swagger URL or upload a file. MockRelay auto-detects field types and creates rules automatically, including ENUM_PICK rules for any enum properties.&lt;/p&gt;

&lt;p&gt;Sample JSON upload(Recommended) — paste or upload a real response body. MockRelay derives the schema from it.&lt;/p&gt;

&lt;p&gt;POJO zip upload(For non complex POJO structures) — upload a zip of your Java model classes. MockRelay parses the field declarations and builds the schema.&lt;/p&gt;




&lt;h2&gt;
  
  
  RECORD → TUNE → REPLAY
&lt;/h2&gt;

&lt;p&gt;The rule engine is powerful but it still requires you to know what rules to define. For a large upstream with dozens of fields, that's work.&lt;/p&gt;

&lt;p&gt;This is where RECORD mode becomes more than just a passthrough.&lt;/p&gt;

&lt;p&gt;Switch a service to RECORD mode and real API traffic flows through and gets captured — full request and response, stored in MongoDB with a 30-day TTL. After enough real traffic is recorded (~30 exchanges is sufficient), you hit &lt;strong&gt;Tune&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tune&lt;/strong&gt; sends those real responses to an LLM (Claude via Spring AI), which analyses the actual values and suggests rules that reflect real production patterns — not random data, not manually guessed ranges, but rules derived from what your upstream actually returns.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2zo7tiy9sk0lfexc5u2s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2zo7tiy9sk0lfexc5u2s.png" alt=" " width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You review the suggestions, edit if needed, and apply. Rules are saved. Recordings are deleted. Switch to REPLAY and your mock data mirrors production.&lt;/p&gt;

&lt;p&gt;▎ &lt;strong&gt;"Import your schema. Record some traffic. Hit Tune. Production-accurate mock data — zero manual rule creation."&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Integration in 60 Seconds
&lt;/h2&gt;

&lt;p&gt;Java (Spring Boot):&lt;/p&gt;

&lt;p&gt;mock.framework.app-id=your-app-id&lt;br&gt;
mock.framework.mock-app-url=&lt;a href="http://mockrelay:8082" rel="noopener noreferrer"&gt;http://mockrelay:8082&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One property file change. RestTemplate is automatically intercepted.&lt;/p&gt;

&lt;p&gt;Angular:&lt;/p&gt;

&lt;p&gt;MockRelayModule.forRoot({&lt;br&gt;
  mockAppUrl: '&lt;a href="http://mockrelay:8082" rel="noopener noreferrer"&gt;http://mockrelay:8082&lt;/a&gt;',&lt;br&gt;
  appId: 'your-app-id',&lt;br&gt;
  services: [&lt;br&gt;
    {&lt;br&gt;
      urlPattern: '&lt;a href="https://your-upstream.com/api/**" rel="noopener noreferrer"&gt;https://your-upstream.com/api/**&lt;/a&gt;',&lt;br&gt;
      serviceId: 'your-upstream'&lt;br&gt;
     }&lt;br&gt;
   ]&lt;br&gt;
 })&lt;br&gt;
One module import. HttpClient is automatically intercepted.&lt;/p&gt;

&lt;p&gt;Mode toggle — just click the toggle in the UI - no redeployment&lt;/p&gt;




&lt;h2&gt;
  
  
  Stack agnostic by design
&lt;/h2&gt;

&lt;p&gt;MockRelay's interceptor model is transport-layer agnostic. The same central mock data service works for any client — the only thing that changes is the interceptor package.&lt;/p&gt;

&lt;p&gt;Java teams drop in a JAR. Angular teams add an npm import. A .NET team would just need a NuGet package. Python apps a .py package. The core platform stays the same regardless of the stack.&lt;/p&gt;

&lt;p&gt;One MockRelay instance. Every team covered — whatever they're building in.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Before and After
&lt;/h2&gt;

&lt;p&gt;The shift isn't just technical — it changes how teams work day to day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvgs0q1kb5s039go9knnk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvgs0q1kb5s039go9knnk.png" alt=" " width="800" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Contract-based testing without any shared environment dependency.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;I built MockRelay because the problem was real and the existing solutions required too much effort to adopt. If a tool has friction, it doesn't get used.&lt;/p&gt;

&lt;p&gt;The goal was simple — give every team an isolated, self-service mock data source they can control from a UI, with zero changes to their application code. Real data when you need it, mock data when you don't. One click either way.&lt;/p&gt;

&lt;p&gt;In this post I covered the architecture, the rule engine, and the RECORD → TUNE → REPLAY flow. In the next one I'll walk through the actual app — what it looks like to onboard a service, configure rules, and switch modes from the UI.&lt;/p&gt;

&lt;p&gt;If you're on a Java/Angular stack and upstream instability is costing your team sprint velocity — follow along.&lt;/p&gt;

&lt;p&gt;Questions, feedback, or war stories about broken upstreams — drop them in the comments.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>llm</category>
      <category>api</category>
      <category>java</category>
    </item>
  </channel>
</rss>
