{"id":12907,"date":"2026-09-14T06:25:23","date_gmt":"2026-09-14T13:25:23","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cosmosdb\/?p=12907"},"modified":"2026-09-14T06:25:23","modified_gmt":"2026-09-14T13:25:23","slug":"multiclouddb-sdk-cross-cloud-portability-in-the-coding-agent-era","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cosmosdb\/multiclouddb-sdk-cross-cloud-portability-in-the-coding-agent-era\/","title":{"rendered":"MulticloudDB SDK: Cross-cloud portability in the coding agent era"},"content":{"rendered":"<p dir=\"auto\">Building cross-cloud solutions with best-of-breed cloud-native databases means learning multiple SDKs, translating queries, handling different errors, and testing across providers. The\u00a0<a href=\"https:\/\/microsoft.github.io\/multiclouddb-sdk-for-java\/\" rel=\"nofollow\">Multicloud DB SDK for Java<\/a>\u00a0lets you share that work across\u00a0<a href=\"https:\/\/learn.microsoft.com\/azure\/cosmos-db\/\" rel=\"nofollow\">Azure Cosmos DB<\/a>, Amazon DynamoDB, and Google Cloud Spanner. You (or your coding agent) write CRUD and query logic against one Java API, with provider selection and connection settings in configuration.<\/p>\n<p dir=\"auto\">We demonstrated one application running unchanged across two providers at\u00a0<a href=\"https:\/\/developer.azurecosmosdb.com\/conf\/\" rel=\"nofollow\">Azure Cosmos DB Conf 2026<\/a>\u00a0on April 28, 2026, in\u00a0<a href=\"https:\/\/www.youtube.com\/watch?v=j6RgAfwwD30\" rel=\"nofollow\">MultiCloudDB: Write Once. Run Anywhere.<\/a>. The SDK is in\u00a0<strong>public preview<\/strong>, with a roadmap for general availability. You&#8217;ll find the current details in the\u00a0<a href=\"https:\/\/github.com\/microsoft\/multiclouddb-sdk-for-java\">repository<\/a>,\u00a0<a href=\"https:\/\/microsoft.github.io\/multiclouddb-sdk-for-java\/\" rel=\"nofollow\">documentation<\/a>, and\u00a0<a href=\"https:\/\/github.com\/microsoft\/multiclouddb-sdk-for-java-samples\">samples<\/a>.<\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h2 dir=\"auto\" tabindex=\"-1\"><\/h2>\n<h2 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Why MulticloudDB SDK?<\/h2>\n<\/div>\n<p dir=\"auto\">Why make every application solve the same portability problems? Each team has to work out how queries, failures, and supported operations differ between databases, then keep that knowledge up to date as providers change. A shared SDK gives teams somewhere to reuse those decisions and tests.<\/p>\n<p dir=\"auto\"><a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2026\/09\/portability-tax.svg\"><img decoding=\"async\" class=\"alignnone size-full wp-image-12908\" role=\"img\" src=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2026\/09\/portability-tax.svg\" alt=\"Diagram showing application code branching into separate provider implementations, tests, errors, and maintenance paths before converging through the MulticloudDB SDK.\" width=\"1440\" height=\"810\" \/><\/a><\/p>\n<p dir=\"auto\"><em>Each provider adds query translation, error handling, tests, and ongoing maintenance.<\/em><\/p>\n<p dir=\"auto\">But if a coding agent can draft a new implementation and its tests in minutes, how much of this work do we still need to share? There are two questions worth separating.<\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h3 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Why not ask a coding agent to rewrite the application for another database?<\/h3>\n<\/div>\n<p dir=\"auto\">You can. The work is checking that the rewritten application still behaves as expected. Does it handle missing values the same way? Does pagination skip or repeat results? What happens when a write is throttled or only part of an operation succeeds? The answers depend on the databases involved, and the tests need to catch those differences. The SDK puts that work into shared adapters and conformance tests, so each application doesn&#8217;t have to start again.<\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h3 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Why use this SDK when a coding agent can generate the abstraction instead?<\/h3>\n<\/div>\n<p dir=\"auto\">The fact that code generation is cheap actually makes a shared, tested abstraction more valuable, not less. As coding agents make implementation faster, the bottleneck shifts from writing code to validating that it behaves correctly. The MulticloudDB SDK gives you a head start on that validation: its shared contract and provider implementations have already been tested together for supported operations. Why make every application repeat that work when developers and coding agents can build on the same tested SDK?<\/p>\n<p dir=\"auto\">A coding agent can build a common interface and the adapters behind it. Establishing that they behave correctly takes much longer and requires detailed knowledge of each database. Someone has to define what the shared API promises, check that each provider can meet those promises, and test query translation, pagination, error handling, and failure scenarios. Coding agents can help with all of this, but generated code and tests can share the same mistaken assumptions. Passing those tests isn&#8217;t enough to establish that the contract is right or that every adapter implements it correctly.<\/p>\n<p dir=\"auto\">That validation takes time and expertise, even when coding agents do much of the coding. The MulticloudDB SDK brings a tested implementation and cross-provider conformance tests that applications can reuse, with Microsoft support planned for general availability. Today it remains a public preview with limited support. Building your own abstraction means your team takes on that validation, ongoing maintenance, and support responsibility.<\/p>\n<p dir=\"auto\">Research on coding agents helps explain why interface design matters here.\u00a0<a href=\"https:\/\/arxiv.org\/abs\/2405.15793\" rel=\"nofollow\">SWE-agent<\/a>\u00a0studied how interfaces for editing code and running tests affect coding agent performance. Anthropic&#8217;s guidance on\u00a0<a href=\"https:\/\/www.anthropic.com\/engineering\/building-effective-agents\" rel=\"nofollow\">simple, composable patterns<\/a>\u00a0and\u00a0<a href=\"https:\/\/www.anthropic.com\/engineering\/writing-tools-for-agents\" rel=\"nofollow\">tool design<\/a>\u00a0also emphasizes clear operations, useful errors, and evaluation. Neither evaluates this SDK, but both inform the approach: give coding agents documented operations and feedback they can use to check their work.<\/p>\n<p dir=\"auto\"><a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2026\/09\/agent-compounding-loop.svg\"><img decoding=\"async\" class=\"alignnone size-full wp-image-12909\" role=\"img\" src=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2026\/09\/agent-compounding-loop.svg\" alt=\"Feedback loop showing developers and coding agents using a stable SDK contract, conformance tests capturing failures, provider knowledge improving adapters, and future applications inheriting those improvements.\" width=\"1440\" height=\"810\" \/><\/a><\/p>\n<p dir=\"auto\"><em>A fix in a shared adapter can help every application that uses it.<\/em><\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h2 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">What the contract covers<\/h2>\n<\/div>\n<ul dir=\"auto\">\n<li><strong>Portable CRUD and query.<\/strong>\u00a0One Java API for create, read, update, and delete, plus a query DSL translated into each native query language.<\/li>\n<li><strong>Provider switching by configuration.<\/strong>\u00a0Select the provider and supply its connection settings without rewriting supported CRUD and query operations.<\/li>\n<li><strong>Capability introspection.<\/strong>\u00a0Check what a provider supports before choosing a code path.<\/li>\n<li><strong>Normalized errors and diagnostics.<\/strong>\u00a0Common failure categories and diagnostic fields, with provider details retained.<\/li>\n<li><strong>Native access.<\/strong>\u00a0<code>nativeExpression()<\/code>\u00a0and\u00a0<code>nativeClient()<\/code>\u00a0let you use provider-specific features. Those calls need their own provider-specific tests.<\/li>\n<li><strong>Cross-provider conformance tests.<\/strong>\u00a0<a href=\"https:\/\/github.com\/microsoft\/multiclouddb-sdk-for-java#testing\">Conformance suites<\/a>\u00a0run the same operations against each provider emulator to check shared behavior.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2026\/09\/semantic-contract.svg\"><img decoding=\"async\" class=\"alignnone wp-image-12910 size-full\" role=\"img\" src=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-content\/uploads\/sites\/52\/2026\/09\/semantic-contract.svg\" alt=\"Diagram titled \u201cAn explicit semantic contract\u201d showing an application using a portable CRUD and query DSL, an explicit key\/error\/diagnostic model, and capability checks before reaching runtime-discovered provider adapters for Azure Cosmos DB, Amazon DynamoDB, and Google Cloud Spanner. Side panels highlight native escape hatches such as nativeExpression() and nativeClient(), plus portability warnings for features like cross-partition queries, server-side ORDER BY, and row-level TTL.\" width=\"1440\" height=\"810\" \/><\/a><\/p>\n<p dir=\"auto\"><em>The shared API sits above provider adapters, with capability checks and access to native features.<\/em><\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h2 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Get started<\/h2>\n<\/div>\n<div class=\"highlight highlight-source-java notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre><span class=\"pl-smi\">MulticloudDbClientConfig<\/span> <span class=\"pl-s1\">config<\/span> = <span class=\"pl-smi\">MulticloudDbClientConfig<\/span>.<span class=\"pl-en\">builder<\/span>()\r\n        .<span class=\"pl-en\">provider<\/span>(<span class=\"pl-smi\">ProviderId<\/span>.<span class=\"pl-en\">fromId<\/span>(<span class=\"pl-s1\">props<\/span>.<span class=\"pl-en\">getProperty<\/span>(<span class=\"pl-s\">\"multiclouddb.provider\"<\/span>)))\r\n        .<span class=\"pl-en\">connection<\/span>(<span class=\"pl-s\">\"endpoint\"<\/span>, <span class=\"pl-s1\">props<\/span>.<span class=\"pl-en\">getProperty<\/span>(<span class=\"pl-s\">\"multiclouddb.connection.endpoint\"<\/span>))\r\n        .<span class=\"pl-en\">connection<\/span>(<span class=\"pl-s\">\"key\"<\/span>, <span class=\"pl-s1\">props<\/span>.<span class=\"pl-en\">getProperty<\/span>(<span class=\"pl-s\">\"multiclouddb.connection.key\"<\/span>))\r\n        .<span class=\"pl-en\">build<\/span>();\r\n\r\n<span class=\"pl-smi\">MulticloudDbClient<\/span> <span class=\"pl-s1\">client<\/span> = <span class=\"pl-smi\">MulticloudDbClientFactory<\/span>.<span class=\"pl-en\">create<\/span>(<span class=\"pl-s1\">config<\/span>);\r\n<span class=\"pl-smi\">ResourceAddress<\/span> <span class=\"pl-s1\">products<\/span> = <span class=\"pl-k\">new<\/span> <span class=\"pl-smi\">ResourceAddress<\/span>(<span class=\"pl-s\">\"appdb\"<\/span>, <span class=\"pl-s\">\"products\"<\/span>);\r\n<span class=\"pl-smi\">Key<\/span> <span class=\"pl-s1\">key<\/span> = <span class=\"pl-smi\">Key<\/span>.<span class=\"pl-en\">of<\/span>(<span class=\"pl-s\">\"books\"<\/span>, <span class=\"pl-s\">\"product-42\"<\/span>);\r\n\r\n<span class=\"pl-s1\">client<\/span>.<span class=\"pl-en\">upsert<\/span>(<span class=\"pl-s1\">products<\/span>, <span class=\"pl-s1\">key<\/span>, <span class=\"pl-s1\">productDocument<\/span>);\r\n<span class=\"pl-smi\">DocumentResult<\/span> <span class=\"pl-s1\">loaded<\/span> = <span class=\"pl-s1\">client<\/span>.<span class=\"pl-en\">read<\/span>(<span class=\"pl-s1\">products<\/span>, <span class=\"pl-s1\">key<\/span>);<\/pre>\n<div class=\"zeroclipboard-container\"><\/div>\n<\/div>\n<p dir=\"auto\">Provider selection stays outside the code:<\/p>\n<div class=\"highlight highlight-source-ini notranslate position-relative overflow-auto\" dir=\"auto\">\n<pre><span class=\"pl-k\">multiclouddb.provider<\/span>=cosmos\r\n<span class=\"pl-k\">multiclouddb.connection.endpoint<\/span>=${DATABASE_ENDPOINT}\r\n<span class=\"pl-k\">multiclouddb.connection.key<\/span>=${DATABASE_KEY}<\/pre>\n<div class=\"zeroclipboard-container\"><\/div>\n<\/div>\n<p dir=\"auto\">For DynamoDB or Spanner, use\u00a0<code>dynamo<\/code>\u00a0or\u00a0<code>spanner<\/code>\u00a0with the appropriate provider module and connection settings. Data modeling and supported capabilities still differ. Check the\u00a0<a href=\"https:\/\/microsoft.github.io\/multiclouddb-sdk-for-java\/\" rel=\"nofollow\">documentation<\/a>\u00a0and\u00a0<a href=\"https:\/\/github.com\/microsoft\/multiclouddb-sdk-for-java#readme\">README<\/a>\u00a0for current dependencies and setup instructions.<\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h2 dir=\"auto\" tabindex=\"-1\"><\/h2>\n<h2 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Try the preview<\/h2>\n<\/div>\n<p dir=\"auto\">Try a few CRUD and query operations from an application you work on against each provider emulator. We&#8217;d like to hear what works, what&#8217;s missing, and where you still need provider-specific code.<\/p>\n<p dir=\"auto\">We plan to expand support when the SDK reaches general availability. Your feedback will help us prioritize that work. Open an\u00a0<a href=\"https:\/\/github.com\/microsoft\/multiclouddb-sdk-for-java\/issues\">issue or feature request<\/a>\u00a0to suggest an operation or database, report unexpected behavior, or discuss your requirements with the team.<\/p>\n<div class=\"markdown-heading\" dir=\"auto\">\n<h2 dir=\"auto\" tabindex=\"-1\"><\/h2>\n<h2 class=\"heading-element\" dir=\"auto\" tabindex=\"-1\">Further reading<\/h2>\n<\/div>\n<ul dir=\"auto\">\n<li><a href=\"https:\/\/github.com\/microsoft\/multiclouddb-sdk-for-java\">MulticloudDB SDK for Java on GitHub<\/a><\/li>\n<li><a href=\"https:\/\/microsoft.github.io\/multiclouddb-sdk-for-java\/\" rel=\"nofollow\">MulticloudDB SDK documentation<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/multiclouddb-sdk-for-java-samples\">MulticloudDB SDK sample applications<\/a><\/li>\n<li><a href=\"https:\/\/developer.azurecosmosdb.com\/conf\/\" rel=\"nofollow\">Azure Cosmos DB Conf 2026<\/a>\u00a0and the\u00a0<a href=\"https:\/\/devblogs.microsoft.com\/cosmosdb\/welcome-to-azure-cosmos-db-conf-2026\/\" rel=\"nofollow\">conference announcement<\/a><\/li>\n<li><a href=\"https:\/\/arxiv.org\/abs\/2405.15793\" rel=\"nofollow\">SWE-agent: Agent-computer interfaces enable automated software engineering<\/a><\/li>\n<li><a href=\"https:\/\/www.anthropic.com\/engineering\/building-effective-agents\" rel=\"nofollow\">Building effective agents<\/a>\u00a0and\u00a0<a href=\"https:\/\/www.anthropic.com\/engineering\/writing-tools-for-agents\" rel=\"nofollow\">Writing tools for agents<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Building cross-cloud solutions with best-of-breed cloud-native databases means learning multiple SDKs, translating queries, handling different errors, and testing across providers. The\u00a0Multicloud DB SDK for Java\u00a0lets you share that work across\u00a0Azure Cosmos DB, Amazon DynamoDB, and Google Cloud Spanner. You (or your coding agent) write CRUD and query logic against one Java API, with provider selection [&hellip;]<\/p>\n","protected":false},"author":9387,"featured_media":12915,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[14],"tags":[],"class_list":["post-12907","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-core-sql-api"],"acf":[],"blog_post_summary":"<p>Building cross-cloud solutions with best-of-breed cloud-native databases means learning multiple SDKs, translating queries, handling different errors, and testing across providers. The\u00a0Multicloud DB SDK for Java\u00a0lets you share that work across\u00a0Azure Cosmos DB, Amazon DynamoDB, and Google Cloud Spanner. You (or your coding agent) write CRUD and query logic against one Java API, with provider selection [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/12907","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/users\/9387"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/comments?post=12907"}],"version-history":[{"count":2,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/12907\/revisions"}],"predecessor-version":[{"id":12917,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/12907\/revisions\/12917"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media\/12915"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media?parent=12907"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/categories?post=12907"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/tags?post=12907"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}