Capa-Java: Why Sidecar Isn't Always the Answer for Hybrid Cloud Java

java dev.to

Capa-Java: Why Sidecar Isn't Always the Answer for Hybrid Cloud Java

Honestly, I've been building Java applications for hybrid cloud for about 7 years now, and I learned the hard way that everyone keeps talking about Sidecar architectures like Dapr and Layotto — and don't get me wrong, they're absolutely the future. But what if I told you that for most existing Java enterprise applications, migrating to a full Sidecar architecture tomorrow is basically impossible?

I've been using Capa-Java in production for three years, and today I want to share the real story: why this rich SDK approach to multi-runtime still matters, when you should use it instead of Sidecar, and the honest pros and cons I've discovered after all this time.


So here's the thing: Sidecar is the future, but we have billions of lines of existing Java

Let me start with my own pain point. A few years back, I was working on a traditional Java enterprise system that had accumulated about 10 years of code. We wanted to move to hybrid cloud — part on-prem, part public cloud — but every service was tightly coupled to our internal middleware APIs.

When Dapr came out, we got really excited. "Great!" we thought. "Let's just refactor everything to use the Sidecar pattern!" But then we started counting: thousands of services, millions of lines of code, dozens of different middleware dependencies... The cost of rewiring everything to go through the Sidecar was going to be enormous. We'd have to pause feature development for at least a year just for the migration.

That's when I found the Capa project, and it changed my thinking completely.

What actually is Capa-Java anyway?

Capa-Java is basically a rich SDK implementation of the Mecha architecture for Java. If you're familiar with Dapr's API concepts, you already understand most of it. The big difference is that instead of running as a separate Sidecar process, Capa runs inside your Java application as an SDK.

Let me show you what it looks like in code. Here's a simple service invocation example using Capa:

import group.rxcloud.capa.sdk.rpc.CapaRpcClient;
import reactor.core.publisher.Mono;
import group.rxcloud.cloudruntimes.utils.TypeRef;

// ...

// You just inject the Capa RPC client, it handles all the middleware complexity
CapaRpcClient capaRpcClient = applicationContext.getBean(CapaRpcClient.class);

// Invoke a service on ANY platform — AWS, Alibaba Cloud, Kubernetes, Dapr...
// The same code works everywhere without modification
Mono<String> result = capaRpcClient.invokeMethod(
    "my-target-service",      // Target app ID
    "sayHello",               // Method name
    "world",                  // Request payload
    TypeRef.STRING            // Response type
);

// Block for synchronous result (or just subscribe if you're reactive)
String response = result.block();
System.out.println("Got response: " + response);
Enter fullscreen mode Exit fullscreen mode

See that? The code doesn't depend on any specific middleware provider API. If you deploy to Alibaba Cloud, Capa loads the Alibaba Cloud SPI implementation. If you deploy to AWS, it loads the AWS implementation. If you're on Kubernetes with Dapr, it just uses Dapr under the hood. Your business code doesn't change at all.

Write once, run anywhere. It sounds like a cliché, but that's exactly what you get here.

The architecture explained simply

Capa uses a layered approach that keeps things clean:

┌─────────────────────────────────────────────────────────┐
│         Application Layer (Your Business Code)          │
│                                                           │
│         Only depends on Capa's standard API              │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│               Capa SDK Layer (Core SDK)                  │
│   Standard API definitions, component loading, SPI      │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│         SPI Implementation Layer (Provider Specific)    │
│  AWS, Alibaba Cloud, Dapr, Kubernetes, custom...        │
└─────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────┐
│               Runtime Layer (Actual Services)            │
└─────────────────────────────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

This separation is what makes everything work. The API is standardized, but the implementation is pluggable. Currently, Capa-Java supports these stable features:

Feature Description Status
RPC/Service Invocation Call services across environments Stable ✅
Configuration Dynamic configuration management Stable ✅
Publish/Subscribe Event messaging Stable ✅
State Management Distributed state Stable ✅
Telemetry Logging, metrics, traces Stable ✅
SQL Database Distributed SQL Alpha 🚧
Scheduled Tasks Job scheduling Alpha 🚧

Getting started is dead simple

If you're using Maven, you just add two dependencies to your pom.xml:

<project>
  <dependencies>
    <!-- Capa core SDK with all standard APIs -->
    <dependency>
      <groupId>group.rxcloud</groupId>
      <artifactId>capa-sdk</artifactId>
      <version>1.0.7.RELEASE</version>
    </dependency>

    <!-- SPI implementation for your target environment -->
    <!-- This example uses the demo implementation for testing -->
    <dependency>
      <groupId>group.rxcloud</groupId>
      <artifactId>capa-sdk-spi-demo</artifactId>
      <version>1.0.7.RELEASE</version>
    </dependency>
  </dependencies>
</project>
Enter fullscreen mode Exit fullscreen mode

That's it. You're ready to go. No extra processes to run, no infrastructure changes just to try it out. You can adopt it incrementally, service by service.

The real question: Should YOU use Capa-Java instead of Dapr/Layotto?

Honestly, this is where it gets interesting. I've been using this in production for three years, so let me break down the pros and cons honestly — no marketing fluff here.

Pros: What I love about Capa-Java

1. Incremental migration is actually possible

This is the big one. You don't need to rewrite your entire application overnight. You can start with one service, then gradually migrate more as you have time. For enterprises with massive legacy Java systems, this is a game-changer. We migrated 100+ services over the course of a year without stopping feature development. That would have been impossible with a full Sidecar rewrite.

2. No extra network hops

Since everything runs inside your JVM, there's no extra network call to a Sidecar proxy. Every invocation is direct. Latency is lower, and you don't have to deal with Sidecar performance issues under high load. I've seen cases where adding a Sidecar increased p99 latency by 2-3x — that doesn't happen with Capa.

3. It's just Java. Your ops team already knows how to handle it.

No new infrastructure to manage, no extra daemons to monitor, no additional configuration for deployment pipelines. It's just another dependency in your Java app. If you can deploy a regular Java app, you can deploy Capa. Your ops team doesn't need to learn a whole new stack just for hybrid cloud.

4. Seamless future migration to Sidecar

Here's the beautiful part: Capa is designed to be compatible with Dapr and Layotto. When your organization is ready to move to full Sidecar architecture, you just swap out the SPI implementation. Your business code doesn't need to change at all. You get a gradual migration path to the future, not a forced cliff.

5. Standard APIs that follow the community

The Capa project keeps API definitions in an independent repository called cloud-runtimes-jvm, and they follow Dapr's API standards. The goal is to make this a community standard, not lock you into another proprietary system. That's a design decision I really respect.

Cons: Where Capa-Java falls short

Nobody talks about the downsides, so I will.

1. You still have language coupling

Since it's an SDK, you're tied to Java (or whichever language you're using). If you have a polyglot environment with multiple languages, you need SDK implementations for each one. They do have alpha versions for Go and Python, but it's not as mature as the Java one. Sidecar gives you true language agnosticism out of the box. That's a real advantage.

2. The SDK versioning problem

When you have thousands of services, you have to manage the Capa SDK version across all of them. Upgrading to a new API version means redeploying every service. With Sidecar, you just upgrade the Sidecar once, and all services get the update immediately. This is where Sidecar really shines — it decouples infrastructure upgrades from application deployments.

3. Alpha features are still alpha

The core features (RPC, config, pub/sub, state, telemetry) are solid in production. But newer features like SQL database integration and scheduled tasks are still in alpha. They're not ready for mission-critical use yet. Dapr has a bigger community and more features fully baked.

4. Smaller community means more self-reliance

This is an open source project, but it's not as big as Dapr. If you run into problems, you can't just search Stack Overflow and find 100 answers. You might need to dig into the code yourself or file an issue. That's just the reality of smaller open source projects. I don't mind it, but it's something you should know going in.

So who is this project actually for?

Based on my experience over the past three years, I think Capa-Java is perfect for you if:

✅ You have an existing large-scale Java enterprise system that needs to move to hybrid cloud incrementally

✅ You don't have the bandwidth for a full Sidecar migration right now

✅ You want lower latency for service-to-service calls

✅ Your ops team isn't ready to manage additional Sidecar infrastructure yet

✅ You want a clear migration path to full Sidecar in the future when you're ready

You should NOT use Capa-Java if:

❌ You're starting a brand new project from scratch (use Dapr/Layotto with Sidecar — it's the future, after all)

❌ You have a polyglot architecture with many different languages

❌ You need the full set of multi-runtime features today (some are still alpha)

❌ You want a huge community with lots of existing examples and answers

I think that's pretty clear, right? No bullshit, just real advice.

My personal story: How this changed our hybrid cloud journey

Let me share a bit of my personal experience. Three years ago, we were stuck. We knew we needed to move to hybrid cloud, we knew our tight coupling to vendor-specific APIs was holding us back, but the estimated migration cost with Sidecar was just way too high. Our leadership wasn't going to approve a full year of just migration work — they needed features to keep the business moving.

When I found Capa, I was skeptical at first. "Another SDK?" I thought. "Isn't Sidecar obviously better?" But then I realized — the problem isn't that Sidecar is bad, the problem is that most of the world isn't ready for it yet. We're in transition. We have billions of lines of existing Java that need a path forward.

Capa gave us that path. We started with one service, got it working, then another, then another. Over the course of a year, we migrated all our services to Capa's standard API. Today, we can deploy the exact same code to our on-prem datacenter, to Alibaba Cloud, to AWS — whatever we need. Vendor lock-in is gone. We didn't stop delivering features. We didn't need to retrain our entire ops team. It just worked.

Honestly, I learned the hard way that architecture isn't just about what's theoretically perfect. It's about what works for your specific situation. Sometimes the "less perfect" architecture that lets you make incremental progress is actually the better architecture.

What's next for Capa-Java?

The project has been around for several years now, and the core features are stable in production. The maintainers are still working on it — they're gradually adding the alpha features and making them more robust. The independent API definition is really promising because it could become a standard that multiple projects can use, regardless of whether you're Team SDK or Team Sidecar.

If you're interested, you should check it out on GitHub:

GitHub: https://github.com/capa-cloud/capa-java

Go star it, open an issue if you find problems, and if you like the project, consider contributing. It's an open source project that fills a real gap that nobody else is really addressing.

Wrapping up

So here's the bottom line: Sidecar architecture is definitely the future of multi-runtime. But that future isn't here for everyone yet. For many of us working with large existing Java systems, we need a bridge between where we are now and where we want to go.

Capa-Java is that bridge. It's not trying to compete with Dapr or replace it — it's helping you get there gradually when a big bang migration isn't possible.

I've been using it in production for three years, and it has served me well. The honest pros and cons are all here — you can decide if it's right for your situation.


Now it's your turn

I'm curious — what's your experience with hybrid cloud migration? Are you working with massive legacy Java systems like I was? Have you tried to migrate to Dapr and gotten sticker shock from the migration cost? Or do you think the rich SDK approach is completely obsolete and we should all just go all-in on Sidecar?

Drop a comment below and let me know what you think. I read every comment and I'm looking forward to hearing different perspectives.

Source: dev.to

arrow_back Back to Tutorials