diff --git a/BUILD.md b/BUILD.md
new file mode 100644
index 0000000..ed2bd67
--- /dev/null
+++ b/BUILD.md
@@ -0,0 +1,208 @@
+# Build Architecture
+
+This document describes the Docker multi-stage build architecture used in this repository.
+
+## Overview
+
+The Dockerfile uses a multi-stage build approach to:
+- Compile Rust code for both native and WebAssembly targets
+- Build and test OpenFeature providers (JavaScript and Java)
+- Package artifacts for distribution
+
+## Build Stage Diagram
+
+The diagram below shows all build stages and their dependencies:
+
+```mermaid
+flowchart TD
+ %% Base images
+ alpine[alpine:3.22]
+ node[node:20-alpine]
+ java[eclipse-temurin:17-jdk]
+
+ %% Rust toolchain and dependency stages
+ alpine --> rust-base[rust-base
Rust toolchain + protoc]
+ rust-base --> rust-deps[rust-deps
Cached Rust dependencies]
+
+ %% Native test/lint base
+ rust-base --> rust-test-base[rust-test-base
Base for native tests/lints]
+ rust-deps -.->|copies cargo cache| rust-test-base
+
+ %% WASM build base
+ rust-base --> wasm-deps[wasm-deps
WASM build environment]
+ rust-deps -.->|copies cargo cache| wasm-deps
+
+ %% Native Rust tests
+ rust-test-base --> confidence-resolver.test[confidence-resolver.test
✓ Core resolver tests]
+ rust-test-base --> wasm-msg.test[wasm-msg.test
✓ WASM msg tests]
+
+ %% Native Rust lints
+ rust-test-base --> confidence-resolver.lint[confidence-resolver.lint
⚡ Core resolver lint]
+ rust-test-base --> wasm-msg.lint[wasm-msg.lint
⚡ WASM msg lint]
+
+ %% WASM build and lint
+ wasm-deps --> wasm-rust-guest.build[wasm-rust-guest.build
🔨 Build WASM resolver]
+ wasm-deps --> wasm-rust-guest.lint[wasm-rust-guest.lint
⚡ WASM guest lint]
+ wasm-deps --> confidence-cloudflare-resolver.lint[confidence-cloudflare-resolver.lint
⚡ Cloudflare lint]
+
+ %% WASM artifact
+ wasm-rust-guest.build --> wasm-rust-guest.artifact[wasm-rust-guest.artifact
📦 confidence_resolver.wasm]
+
+ %% OpenFeature JS provider
+ node --> openfeature-provider-js-base[openfeature-provider-js-base
Node deps + proto gen]
+ wasm-rust-guest.artifact -.->|copies WASM| openfeature-provider-js-base
+ openfeature-provider-js-base --> openfeature-provider-js.test[openfeature-provider-js.test
✓ Provider tests]
+ openfeature-provider-js.test --> openfeature-provider-js.test_e2e[openfeature-provider-js.test_e2e
✓ E2E tests]
+ openfeature-provider-js-base --> openfeature-provider-js.build[openfeature-provider-js.build
🔨 TypeScript build]
+ openfeature-provider-js.build --> openfeature-provider-js.pack[openfeature-provider-js.pack
📦 yarn pack]
+ openfeature-provider-js.pack --> openfeature-provider-js.artifact[openfeature-provider-js.artifact
📦 package.tgz]
+
+ %% OpenFeature Java provider
+ java --> openfeature-provider-java-base[openfeature-provider-java-base
Maven + proto gen]
+ wasm-rust-guest.artifact -.->|copies WASM| openfeature-provider-java-base
+ openfeature-provider-java-base --> openfeature-provider-java.test[openfeature-provider-java.test
✓ Java provider tests]
+ openfeature-provider-java-base --> openfeature-provider-java.build[openfeature-provider-java.build
🔨 Maven build]
+ openfeature-provider-java.build --> openfeature-provider-java.publish[openfeature-provider-java.publish
🚀 Maven Central]
+
+ %% All stage aggregates everything
+ wasm-rust-guest.artifact --> all[all
✅ Complete build]
+ confidence-resolver.test --> all
+ wasm-msg.test --> all
+ openfeature-provider-js.test --> all
+ openfeature-provider-js.test_e2e --> all
+ openfeature-provider-java.test --> all
+ confidence-resolver.lint --> all
+ wasm-msg.lint --> all
+ wasm-rust-guest.lint --> all
+ confidence-cloudflare-resolver.lint --> all
+ openfeature-provider-js.build --> all
+ openfeature-provider-java.build --> all
+
+ %% Styling
+ classDef baseImage fill:#e1f5ff,stroke:#0066cc
+ classDef buildStage fill:#fff4e1,stroke:#ff8c00
+ classDef testStage fill:#e8f5e9,stroke:#2e7d32
+ classDef lintStage fill:#fff3e0,stroke:#f57c00
+ classDef artifact fill:#f3e5f5,stroke:#7b1fa2
+ classDef publish fill:#ffebee,stroke:#c62828
+ classDef final fill:#c8e6c9,stroke:#388e3c
+
+ class alpine,node,java baseImage
+ class rust-base,rust-deps,rust-test-base,wasm-deps,openfeature-provider-js-base,openfeature-provider-java-base baseImage
+ class wasm-rust-guest.build,openfeature-provider-js.build,openfeature-provider-java.build buildStage
+ class confidence-resolver.test,wasm-msg.test,openfeature-provider-js.test,openfeature-provider-js.test_e2e,openfeature-provider-java.test testStage
+ class confidence-resolver.lint,wasm-msg.lint,wasm-rust-guest.lint,confidence-cloudflare-resolver.lint lintStage
+ class wasm-rust-guest.artifact,openfeature-provider-js.pack,openfeature-provider-js.artifact artifact
+ class openfeature-provider-java.publish publish
+ class all final
+```
+
+**Legend:**
+- 🔨 Build stages compile code
+- ✓ Test stages run unit/integration tests
+- ⚡ Lint stages run code quality checks
+- 📦 Artifact stages extract build outputs
+- 🚀 Publish stages deploy to registries
+- ✅ Final `all` stage aggregates everything
+
+## Key Features
+
+### Dependency Caching
+Rust dependencies are compiled once in the `rust-deps` stage and reused across all subsequent builds. This significantly speeds up incremental builds.
+
+### Parallel Execution
+Test and lint stages are independent and can run concurrently, reducing total build time.
+
+### WASM Artifact Sharing
+The core `confidence_resolver.wasm` is built once in `wasm-rust-guest.build` and shared across:
+- OpenFeature JavaScript provider
+- OpenFeature Java provider
+
+### Targeted Builds
+You can build specific components using Docker's `--target` flag:
+
+```bash
+# Build only the WASM artifact
+docker build --target=wasm-rust-guest.artifact .
+
+# Build and extract the npm package
+docker build --target=openfeature-provider-js.artifact .
+
+# Run only JavaScript provider tests
+docker build --target=openfeature-provider-js.test .
+
+# Build everything (default)
+docker build .
+```
+
+## Stage Descriptions
+
+### Base Stages
+
+- **rust-base** (FROM alpine:3.22): Installs Rust toolchain via rustup, protoc, and build dependencies
+- **rust-deps** (FROM rust-base): Compiles all Rust workspace dependencies (cached layer for faster rebuilds)
+- **rust-test-base** (FROM rust-base): Copies dependency cache and source code for native testing/linting
+- **wasm-deps** (FROM rust-base): Copies dependency cache and source code for WASM builds
+- **openfeature-provider-js-base** (FROM node:20-alpine): Node.js environment with Yarn, dependencies, and proto generation
+- **openfeature-provider-java-base** (FROM eclipse-temurin:17-jdk): Java environment with Maven and proto files
+
+### Test Stages
+
+- **confidence-resolver.test** (FROM rust-test-base): Unit tests for core resolver
+- **wasm-msg.test** (FROM rust-test-base): Tests for WASM messaging layer
+- **openfeature-provider-js.test** (FROM openfeature-provider-js-base): Unit tests for JavaScript provider
+- **openfeature-provider-js.test_e2e** (FROM openfeature-provider-js.test): End-to-end tests (requires credentials via Docker secret)
+- **openfeature-provider-java.test** (FROM openfeature-provider-java-base): Tests for Java provider
+
+### Lint Stages
+
+- **confidence-resolver.lint** (FROM rust-test-base): Clippy checks for core resolver
+- **wasm-msg.lint** (FROM rust-test-base): Clippy checks for WASM messaging
+- **wasm-rust-guest.lint** (FROM wasm-deps): Clippy checks for WASM guest
+- **confidence-cloudflare-resolver.lint** (FROM wasm-deps): Clippy checks for Cloudflare resolver
+
+### Build Stages
+
+- **wasm-rust-guest.build** (FROM wasm-deps): Compiles Rust resolver to WebAssembly (wasm32-unknown-unknown target)
+- **openfeature-provider-js.build** (FROM openfeature-provider-js-base): Compiles TypeScript to JavaScript
+- **openfeature-provider-java.build** (FROM openfeature-provider-java-base): Builds Java provider with Maven
+
+### Artifact Stages
+
+- **wasm-rust-guest.artifact** (FROM scratch): Extracts `confidence_resolver.wasm` (rust_guest.wasm → confidence_resolver.wasm)
+- **openfeature-provider-js.pack** (FROM openfeature-provider-js.build): Creates npm package tarball via `yarn pack`
+- **openfeature-provider-js.artifact** (FROM scratch): Extracts package.tgz for distribution
+
+### Publish Stages
+
+- **openfeature-provider-java.publish** (FROM openfeature-provider-java.build): Publishes Java provider to Maven Central (requires GPG and Maven secrets)
+
+### Aggregation Stage
+
+- **all** (FROM scratch): Default stage that ensures all tests, lints, and builds complete successfully by copying marker files
+
+## CI/CD Integration
+
+The build stages are used in GitHub Actions workflows:
+
+- **release-please.yml**: Publishes packages when releases are created
+ - Uses `openfeature-provider-js.artifact` to extract npm package
+ - Uses `openfeature-provider-java.publish` to deploy to Maven Central
+
+## Docker Build Cache
+
+The repository uses Docker layer caching to speed up builds in CI:
+
+```yaml
+cache-from: type=registry,ref=ghcr.io/${{ github.repository }}/cache:main
+```
+
+This allows GitHub Actions to reuse layers from previous builds.
+
+## Dependency Flow
+
+The `rust-deps` stage builds dummy source files to compile all workspace dependencies, creating a cached layer. This cache is then copied into:
+- `rust-test-base` (for native tests and lints)
+- `wasm-deps` (for WASM builds)
+
+This approach ensures dependencies are only compiled once, even when building multiple targets.
diff --git a/Dockerfile b/Dockerfile
index 4ac12d1..56b1731 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -198,165 +198,6 @@ FROM wasm-deps AS confidence-cloudflare-resolver.lint
WORKDIR /workspace/confidence-cloudflare-resolver
RUN make lint
-# ==============================================================================
-# Node.js Host - Run Node.js host example
-# ==============================================================================
-FROM node:20-alpine AS node-host-base
-
-# Install protoc for proto generation
-RUN apk add --no-cache protobuf-dev protoc make
-
-WORKDIR /app
-
-# Enable Corepack for Yarn
-RUN corepack enable
-
-# Copy package files for dependency caching
-COPY wasm/node-host/package.json wasm/node-host/yarn.lock wasm/node-host/.yarnrc.yml ./
-COPY wasm/node-host/Makefile ./
-
-# Copy proto files for generation
-COPY wasm/proto ../proto/
-
-# Build using Makefile (installs deps + generates protos)
-ENV IN_DOCKER_BUILD=1
-RUN make build
-
-# Copy source code
-COPY wasm/node-host/src ./src/
-COPY wasm/node-host/tsconfig.json ./
-
-# Copy WASM module from wasm-rust-guest.artifact
-COPY --from=wasm-rust-guest.artifact /confidence_resolver.wasm ../confidence_resolver.wasm
-
-# Copy resolver state
-COPY wasm/resolver_state.pb ../resolver_state.pb
-
-# ==============================================================================
-# Test Node.js Host (integration test)
-# ==============================================================================
-FROM node-host-base AS node-host.test
-RUN make run
-
-# ==============================================================================
-# Java Host - Run Java host example
-# ==============================================================================
-FROM eclipse-temurin:21-alpine AS java-host-base
-
-# Install Maven and protobuf
-RUN apk add --no-cache maven protobuf-dev protoc make
-
-WORKDIR /app
-
-# Copy pom.xml for dependency caching
-COPY wasm/java-host/pom.xml ./
-COPY wasm/java-host/Makefile ./
-
-# Download dependencies (this layer will be cached)
-RUN mvn dependency:go-offline -q || true
-
-# Copy proto files
-COPY wasm/proto ../proto/
-
-# Copy source code
-COPY wasm/java-host/src ./src/
-
-# Build using Makefile (compiles proto + builds JAR)
-ENV IN_DOCKER_BUILD=1
-RUN make build
-
-# Copy WASM module from wasm-rust-guest.artifact
-COPY --from=wasm-rust-guest.artifact /confidence_resolver.wasm ../confidence_resolver.wasm
-
-# Copy resolver state
-COPY wasm/resolver_state.pb ../resolver_state.pb
-
-# ==============================================================================
-# Test Java Host (integration test)
-# ==============================================================================
-FROM java-host-base AS java-host.test
-RUN make run
-
-# ==============================================================================
-# Go Host - Run Go host example
-# ==============================================================================
-FROM golang:1.23-alpine AS go-host-base
-
-# Install protobuf and protoc-gen-go
-RUN apk add --no-cache protobuf-dev protoc bash make git
-
-WORKDIR /app
-
-# Copy go.mod for dependency caching
-COPY wasm/go-host/go.mod wasm/go-host/go.sum ./
-COPY wasm/go-host/Makefile ./
-
-# Download Go dependencies (this layer will be cached)
-RUN go mod download
-
-# Install protoc-gen-go (pin version for stability)
-RUN go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34
-
-# Copy proto files
-COPY wasm/proto ../proto/
-
-# Copy source code
-COPY wasm/go-host/*.go wasm/go-host/*.sh ./
-
-# Build using Makefile (generates proto + builds)
-ENV IN_DOCKER_BUILD=1
-RUN make build
-
-# Copy WASM module
-COPY --from=wasm-rust-guest.artifact /confidence_resolver.wasm ../confidence_resolver.wasm
-
-# Copy resolver state
-COPY wasm/resolver_state.pb ../resolver_state.pb
-
-# ==============================================================================
-# Test Go Host (integration test)
-# ==============================================================================
-FROM go-host-base AS go-host.test
-RUN make run
-
-# ==============================================================================
-# Python Host - Run Python host example
-# ==============================================================================
-FROM python:3.11-slim AS python-host-base
-
-# Install protobuf and dependencies (libprotobuf-dev includes google proto files)
-RUN apt-get update && \
- apt-get install -y --no-install-recommends protobuf-compiler libprotobuf-dev make && \
- rm -rf /var/lib/apt/lists/*
-
-WORKDIR /app
-
-# Copy Makefile and proto generation script
-COPY wasm/python-host/Makefile ./
-COPY wasm/python-host/generate_proto.py ./
-
-# Copy proto files
-COPY wasm/proto ../proto/
-
-# Build using Makefile (creates venv + installs deps + generates proto)
-ENV IN_DOCKER_BUILD=1
-RUN make build
-
-# Copy source code
-COPY wasm/python-host/*.py ./
-
-# Copy WASM module
-COPY --from=wasm-rust-guest.artifact /confidence_resolver.wasm ../confidence_resolver.wasm
-
-# Copy resolver state
-COPY wasm/resolver_state.pb ../resolver_state.pb
-
-# ==============================================================================
-# Test Python Host (integration test)
-# ==============================================================================
-FROM python-host-base AS python-host.test
-RUN make run
-
# ==============================================================================
# OpenFeature Provider (TypeScript) - Build and test
# ==============================================================================
@@ -514,12 +355,6 @@ COPY --from=openfeature-provider-js.test /app/package.json /markers/test-openfea
COPY --from=openfeature-provider-js.test_e2e /app/package.json /markers/test-openfeature-js-e2e
COPY --from=openfeature-provider-java.test /app/pom.xml /markers/test-openfeature-java
-# Force integration test stages to run (host examples)
-COPY --from=node-host.test /app/package.json /markers/integration-node
-COPY --from=java-host.test /app/pom.xml /markers/integration-java
-COPY --from=go-host.test /app/go.mod /markers/integration-go
-COPY --from=python-host.test /app/Makefile /markers/integration-python
-
# Force lint stages to run by copying marker files
COPY --from=confidence-resolver.lint /workspace/Cargo.toml /markers/lint-resolver
COPY --from=wasm-msg.lint /workspace/Cargo.toml /markers/lint-wasm-msg
diff --git a/README.md b/README.md
index 97dc9b5..0a387a7 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,8 @@ make run-go
make run-python
```
+See [BUILD.md](BUILD.md) for detailed information about the Docker multi-stage build architecture.
+
## Running the example hosts
There are host implementations for different languages in the `wasm` folder.