floci-io/floci-az

Light, fluffy, and always free - Local Azure Emulator

Java

777

352 commits

updated Oct 19, 2026

See the code

README

Floci Azure Floci Azure

Any Cloud. Locally.
Light, fluffy, and always free
No account. No auth token. No feature gates. Just docker compose up.

Latest Release Build Status Docker Pulls Docker Image Size License: MIT GitHub Stars

What is Floci AZ? · Quick Start · Features · Why Floci AZ? · Services · SDKs · Compatibility · Configuration · Docs


What is Floci AZ?

Floci AZ is a free, open-source local Azure emulator for development, testing, and CI.

It gives you Azure-compatible services on your machine without requiring a cloud account, an auth token, or paid feature gates. Point your Azure SDK, CLI, or Terraform at http://localhost:4577 and keep your existing workflows.

Floci AZ is the Azure member of the Floci emulator family.

EmulatorCloudPort
flociAWS4566
floci-azAzure4577
floci-gcpGCP4588
floci-ociOCI4599

Quick Start

# docker-compose.yml
services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock  # required for Azure Functions
docker compose up

Or run directly:

docker run -d --name floci-az \
  -p 4577:4577 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  floci/floci-az:latest

All services are available at http://localhost:4577. Use any account name and key: SharedKey credentials are not validated.

Azure Functions requires access to the Docker socket so Floci AZ can spawn runtime containers on demand. Mount /var/run/docker.sock as shown above. If you don't use Functions, the socket mount is optional.

TLS (for the Cosmos DB Java SDK)

The Azure Cosmos DB Java SDK enforces TLS in gateway mode. Enable the built-in TLS proxy to serve HTTP and HTTPS on the same port:

# docker-compose.yml
services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./data:/app/data        # persist generated cert across restarts
    environment:
      FLOCI_AZ_TLS_ENABLED: "true"
      FLOCI_AZ_HOSTNAME: floci-az   # add Docker service name to cert SANs

The self-signed certificate is generated at startup and cached under data/tls/. Fetch it at runtime from GET http://localhost:4577/_floci/tls-cert to install it into your truststore: no static cert to bundle or import manually.

Terraform / OpenTofu (azurerm) also requires TLS. The provider discovers the cloud over HTTPS (GET https://<host>/metadata/endpoints), so it fails against plain HTTP. See the Terraform / OpenTofu guide.

Features

Local Azure without the cloud account

Run Azure-compatible services locally without an Azure account, auth token, or paid feature gates.

Real Docker where fidelity matters

Azure Functions, Event Hubs, and Cosmos DB engine APIs (MongoDB, PostgreSQL, Cassandra, Gremlin) use real Docker-backed execution instead of shallow mocks.

Drop-in Azure SDK compatibility

Point standard Azure SDK clients at http://localhost:4577. Existing connection strings, credentials, and SDK workflows stay unchanged.

Fast enough for CI

The native image starts in milliseconds and keeps idle memory low, making it practical for local development and test pipelines.

Configurable persistence

Choose from in-memory, persistent, hybrid, and write-ahead log storage depending on the durability profile you need.

Why Floci AZ?

Floci AZ gives you more services than the official local tools, consolidated on a single port, with a native image that starts in milliseconds.

FeatureFloci AZAzuriteFunctions Core Tools
Blob Storage✅✅❌
Queue Storage✅✅❌
Table Storage✅✅❌
Azure Functions✅❌✅
App Configuration✅❌❌
Cosmos DB (SQL API)✅❌❌
Key Vault✅❌❌
Event Hubs✅❌❌
Service Bus✅❌❌
Azure SQL Database✅❌❌
Azure DB for PostgreSQL✅❌❌
AKS (Kubernetes)✅❌❌
Container Apps✅❌❌
API Management✅❌❌
Virtual Machines✅❌❌
Azure Cache for Redis✅❌❌
Container Registry✅❌❌
Container Instances✅❌❌
Event Grid✅❌❌
Azure Monitor / Logs✅❌❌
Communication Email✅❌❌
Managed Identity✅❌❌
Azure Policy✅❌❌
Microsoft Entra ID✅❌❌
Microsoft Graph✅❌❌
Native binary✅❌✅
Unified port✅ (4577)❌❌
Storage modes✅ (persistent/WAL/Hybrid)❌❌
Startup time<100ms (native image)ModerateFast
LicenseMITMITMIT
Azure Cosmos DB Emulator vs Floci AZ

What is the Azure Cosmos DB Emulator?

The Azure Cosmos DB Emulator is Microsoft's official local emulator for Cosmos DB. It ships as a Windows installer or a Windows-container Docker image, exposes a built-in Data Explorer UI, and supports multiple Cosmos DB APIs (SQL, MongoDB, Cassandra, Gremlin, Table). It is a faithful replica of the cloud service, but it carries the full weight of that fidelity.

Head-to-head

FeatureAzure Cosmos DB EmulatorFloci AZ
PlatformWindows-first (Windows containers historically required)Linux-native containers: runs on Mac, Linux, and Windows
Docker image sizeHeavy (~GBs depending on version/base image)Lightweight modular engines (~50 MB to a few hundred MB depending on selected APIs)
Startup timeSlow startup (tens of seconds)On-demand startup: only starts the required Cosmos API engine
RAM requiredHigh memory usage (commonly ≥ 2 GB)Minimal footprint: only active engines consume resources
Cosmos DB APIsSQL (NoSQL), MongoDB, Cassandra, Gremlin, TableSQL (NoSQL), MongoDB, PostgreSQL, Cassandra, Gremlin, Table
Cosmos API implementationMicrosoft proprietary emulatorAPI-specific compatibility engines
NoSQL / SQL API providerNative Cosmos Emulator🟢 Embedded in-process engine: full SQL dialect, no Docker, instant startup
MongoDB API providerNative Cosmos Emulator🟢 MongoDB Community Server: identical wire protocol (BSON + OP_MSG)
PostgreSQL API providerNative Cosmos Emulator🟢 Citus (the exact engine Azure runs): standard JDBC driver, zero code changes
Cassandra API providerNative Cosmos Emulator🟢 ScyllaDB: CQL-compatible, same DataStax driver
Gremlin API providerNative Cosmos Emulator🟡 Apache TinkerPop: standard traversals work; Cosmos extensions not emulated
Table API providerNative Cosmos Emulator🟢 In-memory (embedded): same azure-data-tables SDK, no Docker
Other Azure servicesCosmos DB onlyBlob · Queue · Table · Functions · App Config · Cosmos DB in a unified local Azure stack
HTTPS / certificatesSelf-signed certificates required: must be imported into the OS/JVM trust store or validation disabledPlain HTTP on 4577 by default. Optional TLS: set FLOCI_AZ_TLS_ENABLED=true, and HTTP and HTTPS are served on the same port 4577 via protocol-sniffing proxy; self-signed cert generated at runtime, no static cert bundled, cert available at GET /_floci/tls-cert
Web UI / Data Explorer✅ Built-in❌ API-focused local development environment
Open source❌ Proprietary✅ MIT
CI/CD friendliness⚠️ Heavy images and slower pipelines✅ Fast startup and Linux-friendly containers
Startup modelStarts the full emulator stackStarts only the requested Cosmos API engine
Container strategyMonolithic emulatorModular provider-based architecture
Cloud abstraction philosophyCosmos-specific emulatorUnified cloud abstraction through floci
Primary goalOfficial local Cosmos emulatorLightweight Azure-compatible local development and integration testing
Behavioral parityHigher Azure-specific behavior parityHigh protocol/API compatibility, not full Azure infrastructure emulation
RU/s and global distributionPartial simulation❌ Not fully emulated
Multi-region replicationPartial support❌ Not emulated
Consistency semanticsAzure-orientedBest-effort compatibility depending on engine
Recommended usageFull local Cosmos-focused workflowsFast local development, testing, CI/CD, and lightweight Azure integration workflows

Floci AZ does not aim to fully reproduce Azure Cosmos DB internals or cloud infrastructure behavior.

The goal is to provide high protocol and SDK compatibility through API-specific local engines optimized for:

  • local development
  • integration testing
  • CI/CD pipelines
  • lightweight developer environments

Each Cosmos API is backed by the engine that most closely matches its protocol and driver behavior.

Exact Azure features such as:

  • RU/s throughput semantics
  • global distribution
  • multi-region replication
  • autoscaling
  • exact consistency guarantees
  • Azure internal infrastructure behavior

are intentionally considered out of scope.

When to choose which

Use the official emulator when you need:

  • Full fidelity with the Cosmos DB wire protocol and advanced features (stored procedures, triggers, change feed, TTL, RU/s governance, and multi-region topology simulation).
  • The Data Explorer UI for manual data inspection.

Use Floci AZ when you need:

  • A lightweight, cross-platform dev/test environment that starts in milliseconds.
  • CI/CD pipelines on Linux runners (GitHub Actions, GitLab CI, CircleCI, etc.).
  • Multiple Azure services in a single container: no juggling separate emulators.
  • No TLS certificate headaches.
  • Cosmos DB SQL API coverage is sufficient (CRUD, SQL queries, PATCH, transactional batch, pagination, aggregates, string functions).

Architecture Overview

flowchart LR
    Client["Azure SDK / CLI"]

    subgraph FlociAz ["floci-az, port 4577"]
        Router["HTTP Router\nJAX-RS / Vert.x\nprotocol-sniffing TLS proxy"]

        subgraph Stateless ["Stateless Services"]
            A["App Configuration · Key Vault\nAPI Management · Event Grid\nVirtual Network · Virtual Machines\nContainer Instances · Monitor / Log Analytics\nCommunication Email\nManaged Identity · Azure Policy · Microsoft Entra ID · Microsoft Graph · ARM management plane"]
        end

        subgraph Stateful ["Stateful Services"]
            B["Blob · Queue · Table\nCosmos DB (NoSQL)"]
        end

        subgraph Containers ["Container Services"]
            C["Azure Functions\nEvent Hubs\nService Bus\nAzure SQL\nAKS\nAzure Cache for Redis\nContainer Registry"]
            D["Cosmos engines\nmongo · citus · scylla · gremlin"]
        end

        Router --> Stateless
        Router --> Stateful
        Router --> Containers
        Stateless & Stateful --> Store[("StorageBackend\nmemory · hybrid · persistent · wal")]
    end

    Docker["Docker Engine"]
    Client -->|"HTTP/HTTPS :4577\nAzure wire protocol"| Router
    Containers -->|"Docker API\nsidecars & function containers"| Docker

Supported Services

ServiceRoutingNotable operations
Blob Storage/{account}/Create/delete containers, upload/download/delete blobs, list blobs; ADLS Gen2 DFS filesystem/path operations with Hadoop ABFS 3.3.4 compatibility; user delegation key/SAS
Azure SignalR Service/server/, /client/, *.service.signalr.netDefault mode over WebSockets; ASP.NET Core hubs, JSON/MessagePack, groups, users, and broadcasts. Per-account isolation through {account}.service.signalr.net hostnames
Queue Storage/{account}-queue/Create/delete queues, send/receive/peek/delete messages, visibility timeout
Table Storage/{account}-table/Create/delete tables, insert/get/update/upsert/delete entities; OData $filter / $select / $top; server-side pagination (continuation tokens); ETag optimistic concurrency; Entity Group Transactions ($batch)
Azure Functions/{account}-functions/Deploy & invoke HTTP-triggered functions (node, python, java, dotnet); warm-container pool
App Configuration/{account}-appconfig/Key-values, labels, feature flags, snapshots (async provisioning), revisions, locks, ETags; pagination (@nextLink), $select, tags filtering, Accept-Datetime time-travel, Sync-Token
Cosmos DB (NoSQL)/{account}-cosmos/Databases, containers, documents CRUD + full SQL queries: always-on, no Docker. PATCH; transactional batch.
Cosmos DB NoSQL (embedded)/{account}-cosmos-nosql/Same embedded SQL engine as above, exposed as a named engine endpoint. Opt-in with FLOCI_AZ_SERVICES_COSMOS_ENGINES_NOSQL_ENABLED=true; no Docker required.
Key Vault/{account}-keyvault/Self-signed certificates with PFX/PEM secrets; Secrets CRUD, versioning, soft-delete, properties update; Keys CRUD, backup/restore, rotation, RSA/EC/oct crypto (encrypt/decrypt/sign/verify/wrap/unwrap), /rng; Managed HSM (/{account}-managedhsm/)
Event HubsAMQP :5672 / Kafka :9093AMQP 1.0 (Artemis sidecar), Kafka-compatible (Redpanda, opt-in)
Service Bus/{account}-servicebus/ + AMQP :5673Queues, topics, subscriptions (created dynamically); AMQP 1.0 data plane via Artemis sidecar, or mocked (management plane only)
Azure SQL DatabaseARM path + /{account}-sql/Servers, databases, firewall rules; ARM-only by default, optional managed SQL Server 2025 containers
Azure Database for PostgreSQLARM path (Microsoft.DBforPostgreSQL) + /{account}-postgres/Flexible servers, databases, firewall rules, configurations; Docker-backed postgres:17-alpine containers (no EULA), dynamic port allocation, or mocked
Azure Database for MySQLARM path (Microsoft.DBforMySQL) + /{account}-mysql/Flexible servers, databases, firewall rules, configurations; Docker-backed mysql:8.0 containers (no EULA), dynamic port allocation, or mocked
Azure Database for MariaDBARM path (Microsoft.DBforMariaDB) + /{account}-mariadb/Servers (single-server model), databases, firewall rules, configurations; Docker-backed mariadb:10.11 containers (no EULA), dynamic port allocation, or mocked
Azure Kubernetes ServiceARM path (Microsoft.ContainerService)CreateOrUpdate, Get, Delete, List, agent pools, kubeconfig (listClusterAdminCredential); real k3s containers or mocked
Azure Container AppsARM path (Microsoft.App) + environment-specific app FQDNManaged environment/app CRUD, Single/Multiple revisions, secrets, min/max replicas, Docker-backed HTTP ingress or mocked
API ManagementARM path (Microsoft.ApiManagement) + /{account}-apim/{service}/In-process APIM emulator for ARM resources, gateway routing, products/subscriptions, named values, backends, OpenAPI import, and a focused policy subset
Virtual NetworkARM path (Microsoft.Network)VNet, subnet, NIC, public IP, NSG, private DNS zone (+ virtual network links, record sets), private endpoint (+ private DNS zone groups), and private link service ARM resources; subnet listing is scoped to the parent VNet; NIC private IPs are synthesized for VM/Terraform compatibility
Virtual MachinesARM path (Microsoft.Compute)VM lifecycle (create/start/stop/deallocate/restart/delete/list), instanceView power state; mocked by default (no Docker), or one Linux container per VM with mocked: false
Azure Cache for RedisARM path (Microsoft.Cache)Cache CRUD, listKeys/regenerateKey; real valkey/valkey:8-alpine containers (data plane, primary key as password) or mocked; non-SSL port
Azure Container RegistryARM path (Microsoft.ContainerRegistry)Registry CRUD, listCredentials/regenerateCredential, checkNameAvailability; one shared registry:2 (Docker Registry V2 push/pull, anonymous on its published port); az acr login through the Entra token exchange on {name}.azurecr.io; or mocked
Azure Container InstancesARM path (Microsoft.ContainerInstance)Container group lifecycle (create/update/delete/list by rg + subscription), start/stop/restart with spec-exact LRO shapes, container logs, instanceView, azurerm-safe read-backs (ports/resources always present, canonical enum casing, secrets never echoed); real Docker containers with shared-netns pod semantics (localhost between group members) or mocked
Event GridARM path (Microsoft.EventGrid) + /{topic}-eventgrid/api/eventsCustom Topics, listKeys/regenerateKey, webhook eventSubscriptions with subject/eventType filters; publish in Event Grid + CloudEvents 1.0 schemas; async webhook delivery with retry; SubscriptionValidationEvent handshake; HTTP-only (no sidecar)
Azure Monitor / Log AnalyticsARM path (Microsoft.OperationalInsights / Microsoft.Insights) + /dataCollectionRules/{id}/streams/{stream} + /v1/workspaces/{id}/queryWorkspaces, Data Collection Endpoints/Rules; Logs Ingestion API; Log Analytics query with a KQL subset (where/project/take/limit + timespan); HTTP-only (no sidecar)
Communication Services Email/emails:send + /emails/operations/{id} + /emailMessages + ARM path (Microsoft.Communication)ACS Email send + status polling; in-memory inspection mailbox (Mailpit-style GET /emailMessages); communication/email services + domains via ARM; captures messages locally, no real delivery; HTTP-only (no sidecar)
Managed IdentityARM path (Microsoft.ManagedIdentity) + /metadata/identity/oauth2/tokenUser-assigned identities (server-generated principalId/clientId), federated identity credentials, system-assigned identities/default; IMDS token endpoint for ManagedIdentityCredential (point the SDK at the emulator with AZURE_POD_IDENTITY_AUTHORITY_HOST); v1.0 JWTs signed with the Entra key, verifiable via JWKS; HTTP-only (no sidecar)
Azure PolicyARM path (Microsoft.Authorization/policy*)Policy definitions, set definitions (initiatives), assignments and exemptions at management-group, subscription, resource-group and resource scope; $filter scope forms (atScope(), atExactScope(), atScopeAndBelow()); server-side scope, instanceId, definitionVersion, audit metadata and assignment identities; referential integrity on delete. Control plane only: rules are stored, never evaluated, and no built-ins are seeded; HTTP-only (no sidecar)
API Management details

Floci AZ includes an in-process API Management emulator intended for local development, SDK compatibility tests, and CI workflows that need APIM-shaped ARM resources plus a lightweight gateway. It is not a full Azure APIM gateway implementation.

APIM is available through:

  • ARM-compatible resource paths under Microsoft.ApiManagement.
  • Gateway routes under /{account}-apim/{serviceName}/{apiPath...}. With the default account this is http://localhost:4577/devstoreaccount1-apim/{serviceName}/....

Supported

  • Management service resources: create, get, list, delete.
  • API resources: create, get, list, delete.
  • Operation resources: create, get, list, delete.
  • Policy resources at service, API, and operation scope.
  • Product resources and product-to-API links.
  • Subscription resources with gateway subscription-key enforcement.
  • Named values, including secret named values whose properties.value is not exposed in ARM responses.
  • Backends and <set-backend-service backend-id="...">.
  • OpenAPI JSON import for APIs, including operation generation from paths.
  • OpenAPI reimport behavior that replaces previous generated operations.
  • Gateway route matching for API paths and operation URL templates.
  • Basic backend proxying when an API serviceUrl or backend policy is configured.

Supported Policy Subset

The policy engine intentionally supports a focused subset:

  • <set-header> with exists-action="override", skip, append, and delete.
  • <set-query-parameter> with exists-action="override", skip, and delete.
  • <rewrite-uri template="...">.
  • <set-backend-service base-url="...">.
  • <set-backend-service backend-id="...">.
  • <return-response>.
  • <set-status code="..."> inside return-response.
  • <set-body> inside return-response.
  • Named value interpolation with {{name}} in supported policy values.

Partial or Out of Scope

The APIM emulator is intentionally scoped. These features are not fully emulated:

  • The full APIM policy language and C# policy expressions.
  • JWT validation, OAuth/OIDC flows, certificates, mTLS, and managed identities.
  • API revisions, API versions, version sets, releases, tags, groups, users, loggers, diagnostics, named value Key Vault references, and developer portal behavior.
  • APIM networking, private endpoints, custom domains, DNS, scale units, regions, SKU behavior, and deployment lifecycle timing.
  • Exact APIM error formats, tracing, analytics, caching, rate-limit counters, quota counters, and distributed gateway behavior.

The current goal is practical local parity for common APIM provisioning and gateway tests, not full Azure infrastructure simulation.

Real Docker Integration

Floci AZ uses real Docker containers when in-process emulation would reduce fidelity.

ServiceDefault imageWhat is real
Azure Functionsmcr.microsoft.com/azure-functions/<runtime>Real Azure Functions runtime, warm container pool
Event Hubs AMQPapache/activemq-artemisFull AMQP 1.0 broker
Event Hubs Kafkaredpandadata/redpandaKafka-compatible broker (opt-in)
Cosmos DB MongoDBmongo:7MongoDB Community Server, full wire protocol
Cosmos DB PostgreSQLcitusdata/citusCitus: the exact engine Azure runs
Cosmos DB Cassandrascylladb/scylla:6.2CQL-compatible drop-in
Cosmos DB Gremlintinkerpop/gremlin-serverApache TinkerPop: standard Gremlin traversals
Azure SQL Databasemcr.microsoft.com/mssql/server:2025-latestOptional managed SQL Server engine (per server)
Azure Database for PostgreSQLpostgres:17-alpinePostgreSQL engine (per flexible server)
Azure Database for MySQLmysql:8.0MySQL engine (per flexible server)
Azure Database for MariaDBmariadb:10.11MariaDB engine (per server)
AKSrancher/k3s:latestKubernetes API server via k3s
Azure Container AppsUser-provided imagesRevision replicas with HTTP ingress through floci-az
Azure Cache for Redisvalkey/valkey:8-alpineRedis / Valkey protocol (per cache)
Azure Container Registryregistry:2OCI-compatible registry for docker push and docker pull (shared)

Docker-backed services require the Docker socket:

docker run -d --name floci-az \
  -p 4577:4577 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  floci/floci-az:latest

The Cosmos DB multi-API engines (MongoDB, PostgreSQL, Cassandra, Gremlin, plus the embedded NoSQL and Table engines) are disabled by default and configured separately: see the Cosmos DB engine configuration docs.

Persistence and Storage Modes

Floci AZ features the same flexible storage architecture as Floci. Configure the storage mode globally via FLOCI_AZ_STORAGE_MODE or override it per service.

ModeBehaviorBest for...Durability
memory (Default)Entirely in-RAM. Data is lost when the container stops.Speed, ephemeral testing, CI pipelines.❌ None
persistentData is loaded at startup and flushed to disk on graceful shutdown.Simple local dev with state preservation.⚠️ Medium
hybridIn-memory performance with periodic async flushing (every 5s).The perfect balance of speed and safety.✅ Good
walWrite-Ahead Log. Every mutation is logged to disk before responding.Maximum durability for critical state.💎 Highest

[!TIP] Use hybrid for a "it just works" experience that survives container restarts. For ephemeral integration tests where state doesn't matter, keep the default memory mode for maximum performance.

SDK Integration

Floci AZ uses path-style routing:

ServiceEndpointNotes
Blobhttp://localhost:4577/{accountName}
Data Lake Storage Gen2http://localhost:4577/{accountName}Use the {accountName}.dfs.core.windows.net Host header; maps to the Blob backend and supports Hadoop ABFS 3.3.4 filesystem/path flows, including HNS detection, conditional create/overwrite, properties/XAttrs, ACL metadata, leases, append/flush, listing, status, rename, and delete
Queuehttp://localhost:4577/{accountName}-queue
Tablehttp://localhost:4577/{accountName}-table
Functionshttp://localhost:4577/{accountName}-functions
App Configurationhttp://localhost:4577/{accountName}-appconfigSome SDKs require an https:// URL: use a ForceHttp transport policy to rewrite to HTTP
Cosmos DBhttp://localhost:4577/{accountName}-cosmosPython / Node SDKs. Java SDK: enable TLS (FLOCI_AZ_TLS_ENABLED=true) and use https://localhost:4577: the SDK enforces TLS; cert auto-generated at runtime, fetch from GET /_floci/tls-cert
Key Vaulthttp://localhost:4577/{accountName}-keyvaultSome SDKs require an https:// URL: use a ForceHttp transport policy to rewrite to HTTP
Event HubsAMQP amqp://localhost:5672 · Kafka localhost:9093

The standard development storage connection string works out of the box:

DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://localhost:4577/devstoreaccount1;QueueEndpoint=http://localhost:4577/devstoreaccount1-queue;TableEndpoint=http://localhost:4577/devstoreaccount1-table;
Python
# azure-storage-blob
from azure.storage.blob import BlobServiceClient

conn_str = (
    "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;"
    "AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;"
    "BlobEndpoint=http://localhost:4577/devstoreaccount1;"
)

client = BlobServiceClient.from_connection_string(conn_str)
client.create_container("my-container")

blob = client.get_container_client("my-container").get_blob_client("hello.txt")
blob.upload_blob(b"Hello from floci-az!")
print(blob.download_blob().readall())
# azure-storage-queue
from azure.storage.queue import QueueServiceClient

conn_str = (
    "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;"
    "AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;"
    "QueueEndpoint=http://localhost:4577/devstoreaccount1-queue;"
)

client = QueueServiceClient.from_connection_string(conn_str)
queue = client.create_queue("my-queue")
queue.send_message("Hello from floci-az!")
print(list(queue.receive_messages())[0].content)
# azure-data-tables
from azure.data.tables import TableServiceClient

conn_str = (
    "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;"
    "AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;"
    "TableEndpoint=http://localhost:4577/devstoreaccount1-table;"
)

service = TableServiceClient.from_connection_string(conn_str)
table = service.create_table("MyTable")
table.create_entity({"PartitionKey": "pk1", "RowKey": "rk1", "Value": "hello"})
print(table.get_entity("pk1", "rk1")["Value"])
Java
BlobServiceClient client = new BlobServiceClientBuilder()
    .connectionString(
        "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;" +
        "AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;" +
        "BlobEndpoint=http://localhost:4577/devstoreaccount1;")
    .buildClient();

client.createBlobContainer("my-container");

BlobClient blob = client.getBlobContainerClient("my-container").getBlobClient("hello.txt");
blob.upload(new ByteArrayInputStream("Hello from floci-az!".getBytes()), 20);
Node.js / TypeScript
import { BlobServiceClient } from "@azure/storage-blob";

const CONN =
  "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;" +
  "AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;" +
  "BlobEndpoint=http://localhost:4577/devstoreaccount1;";

const client = BlobServiceClient.fromConnectionString(CONN);
const { containerClient } = await client.createContainer("my-container");

const blob = containerClient.getBlockBlobClient("hello.txt");
await blob.upload(Buffer.from("Hello from floci-az!"), 20);
console.log((await blob.downloadToBuffer()).toString());
Azure Functions

Functions are managed via a REST management API and invoked over HTTP. The emulator spawns a real Azure Functions runtime container on first invoke and keeps it warm for subsequent calls.

BASE="http://localhost:4577/devstoreaccount1-functions"

# Create a function app
curl -s -X PUT "$BASE/admin/apps/my-app" \
  -H "Content-Type: application/json" \
  -d '{"runtime":"node","environment":{"MY_VAR":"hello"}}'

# Deploy a function (ZIP of your function code, base64-encoded)
ZIP_B64=$(base64 < my-function.zip)
curl -s -X PUT "$BASE/admin/apps/my-app/functions/hello" \
  -H "Content-Type: application/json" \
  -d "{\"handler\":\"index.handler\",\"timeoutSeconds\":60,\"zipBase64\":\"$ZIP_B64\"}"

# Invoke
curl "$BASE/api/my-app/hello?msg=world"

Supported runtimes: node, python, java, dotnet.

To select a Linux language version, pass the Azure-compatible linuxFxVersion. For example, Python 3.12 uses {"runtime":"python","linuxFxVersion":"Python|3.12"}.

Azure CLI (azfloci)

azfloci is a companion CLI that acts as a transparent proxy for the official Azure CLI (az). It automatically injects the correct connection strings and disables SSL verification so you can use standard az commands against the local emulator.

# Optional: alias azfloci as az for a seamless experience
alias az='python3 /path/to/floci-az/azfloci/azfloci.py'

# Initialize or get connection string info
az setup

# Blob Storage
az storage container create --name my-container
az storage blob upload --container-name my-container --name hello.txt --file hello.txt
az storage blob list --container-name my-container --output table

# Queue Storage
az storage queue create --name my-queue
az storage message put --queue-name my-queue --content "Hello from CLI"

# Table Storage
az storage table create --name MyTable

azfloci automatically detects --account-name (defaulting to devstoreaccount1) and constructs the appropriate local endpoint.

When your app runs in a separate container

Set the service name as the hostname so returned URLs resolve correctly inside Docker Compose:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - app-net

  my-app:
    environment:
      AZURE_BLOB_ENDPOINT: http://floci-az:4577/devstoreaccount1
      AZURE_QUEUE_ENDPOINT: http://floci-az:4577/devstoreaccount1-queue
      AZURE_TABLE_ENDPOINT: http://floci-az:4577/devstoreaccount1-table
    depends_on:
      floci-az:
        condition: service_healthy
    networks:
      - app-net

networks:
  app-net:

Compatibility Testing

The compatibility-tests directory validates Floci AZ across SDKs and tooling workflows. Each directory is one suite. App Configuration, Key Vault, Event Hubs, and Service Bus are exercised inside the SDK suites rather than as standalone modules.

ModuleLanguage / ToolCoverage
sdk-test-pythonPython 3Blob, Queue, Table, Cosmos, App Configuration, Key Vault, ACR, Redis, VM, Managed Identity
sdk-test-javaJava 21Storage, Cosmos (+ Mongo/PostgreSQL/Cassandra/Gremlin/Table/NoSQL engines), App Config, Key Vault, Event Hubs, Service Bus, Functions, Container Apps, API Management, SQL, PostgreSQL (Flexible Server), Managed Identity, Policy
sdk-test-nodeNode.jsApp Configuration, Blob, Cosmos, Event Hubs, Key Vault, Queue, Table, Service Bus, Entra ID, Managed Identity
sdk-test-dotnet.NETBlob service SAS, Cosmos (+ bracket properties, point partition, transactional batch), Key Vault (+ certificates, timestamps), Service Bus (+ lock renewal, metadata, peek-lock), SignalR. The only suite covering SignalR
sdk-test-cpp †C++ 17Blob, Queue: Lifecycle plus the bodyless-error path no other SDK reproduces
compat-terraformTerraformazurerm provider apply/destroy (resource group, storage, key vault, VNet, VM, Redis, ACR)
compat-opentofuOpenTofuSame azurerm suite via tofu, plus PostgreSQL Flexible Server (server + database)
compat-azcli ‡Azure CLIaz against a custom cloud with Entra service-principal login

† Built from source via vcpkg, so the image takes ~6 min cold (seconds if warm).

‡ Ships with the Entra ID feature (#23).

Run the suites against a running container:

make test-python-compat
make test-java-compat
make test-node-compat
make test-cpp-compat
make test-cosmos-all    # Cosmos engine tests: MongoDB · PostgreSQL · Cassandra · Gremlin · Table · NoSQL (requires Docker)
make test-iac-compat    # Terraform + OpenTofu
make compat-docker      # full matrix

Migrating from Azurite

Azurite users can point their existing connection strings at Floci AZ with a single endpoint change.

# Before (Azurite default)
DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02...;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;

# After (Floci AZ, single port)
DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02...;BlobEndpoint=http://localhost:4577/devstoreaccount1;QueueEndpoint=http://localhost:4577/devstoreaccount1-queue;TableEndpoint=http://localhost:4577/devstoreaccount1-table;

The account name and key are the same. Floci AZ consolidates all services onto port 4577: no more separate ports per service.

Image Tags

All images are native (multi-arch linux/amd64 + linux/arm64).

ChannelStandardCompat with Azure CLI and azfloci
Release, floatinglatestlatest-compat
Release, pinnedx.y.zx.y.z-compat
Nightly, floatingnightlynightly-compat
Nightly, datednightly-mmddyyyynightly-mmddyyyy-compat

Use latest for stable releases, a pinned version for reproducible builds, and nightly to track main.

image: floci/floci-az:latest         # recommended
image: floci/floci-az:latest-compat  # includes Azure CLI and azfloci
image: floci/floci-az:x.y.z          # pinned release
image: floci/floci-az:nightly        # track main

Release train

Stable releases ship on the 15th and the last day of each month, cut automatically at 00:30 US Central time. Between trains, floci/floci-az:nightly tracks main. Every merged fix is available the next day, and dated nightly-mmddyyyy tags let you pin a specific night's build.

Versions are derived from Conventional Commits by semantic-release; CHANGELOG.md is generated, never hand-edited. Releases are cut from main only: there are no maintenance branches.

Configuration

All settings are overridable via environment variables (FLOCI_AZ_ prefix).

VariableDefaultDescription
FLOCI_AZ_PORT4577Port exposed by the API
FLOCI_AZ_BASE_URLhttp://localhost:4577Base URL used when the emulator returns service URLs
FLOCI_AZ_HOSTNAMEUnsetHostname added to returned URLs and TLS cert SANs when running inside Docker Compose
FLOCI_AZ_TLS_ENABLEDfalseEnable HTTP+HTTPS on the same port via protocol-sniffing proxy
FLOCI_AZ_PARITYcompatHow closely the ARM platform answers follow Azure: compat keeps every response as floci-az has always given it, azure gives Azure's answers (resource-group update and cascading delete, listed subscriptions), strict adds Azure's refusals (unknown subscription or resource group). See the ARM docs
FLOCI_AZ_STORAGE_MODEmemoryStorage mode: memory, persistent, hybrid, or wal
FLOCI_AZ_STORAGE_PATH/app/dataDirectory used for persisted state
FLOCI_AZ_DOCKER_DOCKER_HOSTunix:///var/run/docker.sockDocker socket used to spawn function and sidecar containers
FLOCI_AZ_DOCKER_ENDPOINT_MODEautoHow sidecar containers are addressed: auto (container name or IP and internal port inside Docker, localhost and the published port otherwise) or published (the Docker daemon's host and the published port, for remote daemons such as docker-in-docker or kubedock)
FLOCI_AZ_DOCKER_RESOURCE_NAMESPACE(unset)Namespace inserted into the name of every container and volume floci-az creates (floci-az-<ns>-...) and added as the floci_namespace label, so parallel emulator instances on one Docker host don't collide

Per-service enable flags (FLOCI_AZ_SERVICES_<SERVICE>_ENABLED), TLS certificate paths, Cosmos engine settings, and the rest are documented in the full reference.

Full reference: configuration docs

Per-service storage override

You can set a different storage mode for each service independently:

# docker-compose.yml
environment:
  FLOCI_AZ_STORAGE_MODE: memory
  FLOCI_AZ_STORAGE_SERVICES_BLOB_MODE: wal

Multi-container Docker Compose

When your application runs in a separate container, use the service name as the hostname so returned URLs (such as blob/queue/table endpoints) resolve correctly:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock  # required for Azure Functions
    networks:
      - app-net

  my-app:
    environment:
      AZURE_BLOB_ENDPOINT: http://floci-az:4577/devstoreaccount1
      AZURE_QUEUE_ENDPOINT: http://floci-az:4577/devstoreaccount1-queue
      AZURE_TABLE_ENDPOINT: http://floci-az:4577/devstoreaccount1-table
      AZURE_FUNCTIONS_ENDPOINT: http://floci-az:4577/devstoreaccount1-functions
      AZURE_APPCONFIG_ENDPOINT: https://floci-az:4577/devstoreaccount1-appconfig  # https required by App Config SDK (use ForceHttp transport in your client)
    depends_on:
      floci-az:
        condition: service_healthy
    networks:
      - app-net

networks:
  app-net:

For the Cosmos DB multi-API engines (MongoDB, PostgreSQL, Cassandra, Gremlin, and the embedded NoSQL and Table engines), including enable flags, image/port overrides, the /connect endpoint, and SDK examples, see the Cosmos DB engine configuration docs.

Cosmos DB API parity rationale

Each engine's compatibility level is determined by how closely the underlying runtime matches what Azure Cosmos DB actually runs in production.


🟢 PostgreSQL API: very high parity

Azure Cosmos DB for PostgreSQL is Citus, a distributed PostgreSQL extension developed by the same team that runs inside Azure. The wire protocol, query language, and drivers are identical to vanilla PostgreSQL.

  • Client SDK: standard PostgreSQL JDBC driver (org.postgresql:postgresql), the same driver you use in production, unchanged. Official quickstart.
  • Engine: citusdata/citus Docker image (the exact same project).
  • Known gaps: Azure-specific HA/scaling, multi-region replication, and Azure RBAC are infrastructure features with no local equivalent.
  • Note: Microsoft is retiring this API. The recommended migration path is Azure Database for PostgreSQL (Elastic Clusters) or Cosmos DB for NoSQL.

🟢 MongoDB API: very high parity

Azure Cosmos DB for MongoDB exposes the full MongoDB wire protocol (BSON + OP_MSG). Connecting with any MongoDB driver targets the same binary framing and command set regardless of whether the server is a real mongod or the Azure Cosmos service.

  • Client SDK: any MongoDB driver (mongodb-driver-sync, pymongo, mongodb Node.js package), and the connection string format is identical.
  • Engine: mongo:7 Community Server, the reference implementation of the protocol.
  • Known gaps: Azure-specific index types (wildcard compound), $lookup with let in some API versions, and RU/s throughput governance.

🟢 Table API: high parity

The Azure Table Storage REST API is a straightforward OData/JSON HTTP API. floci-az implements it directly in-process, with no Docker required. Because the protocol is pure HTTP with a well-documented spec, compatibility is structural: the same SDK targets the same URLs and receives the same JSON shapes.

  • Client SDK: azure-data-tables SDK for Java, Python, Node.js, .NET. Use the official Cosmos DB for Table pattern: .endpoint() + AzureNamedKeyCredential. See Java quickstart. The connection string format is also supported for backward compatibility.
  • Engine: in-memory (ConcurrentHashMap), instant startup, zero Docker overhead.
  • Supported query operators: OData eq, ne, gt, ge, lt, le, and, or, not; $filter, $top, $select.
  • Known gaps: Cosmos DB RU/s throughput model, TTL-based expiry, server-side pagination continuation tokens beyond $top.

🟢 Cassandra API: high parity

Azure Cosmos DB for Cassandra implements the Apache Cassandra CQL binary wire protocol (native transport, port 9042). Any CQL-compatible driver connects transparently. ScyllaDB is a CQL-compatible drop-in replacement that shares the same driver ecosystem.

  • Client SDK: DataStax Java Driver (com.datastax.oss:java-driver-core), cassandra-driver-core, or any CQL v4 client. The contact point and port are all you need to change.
  • Engine: scylladb/scylla (default) or any Apache Cassandra image via the image override.
  • Known gaps: some Cosmos-specific TTL semantics, Cosmos RBAC, Cassandra LWT (lightweight transactions) edge cases, and ALLOW FILTERING query restrictions differ slightly.

🟡 Gremlin API: medium parity

Azure Cosmos DB for Gremlin is built on Apache TinkerPop. Standard Gremlin traversals work identically. However, Cosmos DB adds proprietary extensions (partition key semantics, bulk executor, certain graph-level operations) that TinkerPop Gremlin Server does not implement.

  • Client SDK: gremlin-driver (org.apache.tinkerpop:gremlin-driver), connecting via WebSocket to port 8182, same as in production.
  • Engine: tinkerpop/gremlin-server.
  • Known gaps: Cosmos DB pk partition key column requirement, addE/addV Cosmos extensions, bulk import API, and multi-region graph consistency guarantees.

🟢 NoSQL / SQL API: very high parity (embedded engine)

Both NoSQL endpoints are in-process, with no Docker and instant startup:

EndpointUse caseSQL queriesDocker
{account}-cosmosCRUD + SQL, always-on✅ Full SQL dialectNo
{account}-cosmos-nosqlNamed engine endpoint, opt-in✅ Full SQL dialectNo

The embedded NoSQL engine implements the Azure Cosmos DB SQL grammar in-process:

  • SELECT, WHERE, ORDER BY, GROUP BY, OFFSET LIMIT, SELECT TOP, SELECT DISTINCT
  • Aggregates: COUNT, SUM, AVG, MIN, MAX
  • Predicates: =, !=, IN, BETWEEN, LIKE, NOT, AND, OR, IS_DEFINED, IS_NULL, CONTAINS, STARTSWITH, ENDSWITH, STRINGEQUALS, REGEXMATCH, ARRAY_CONTAINS
  • Conditional: IIF(condition, trueVal, falseVal)
  • String functions: LOWER, UPPER, LENGTH, CONCAT, SUBSTRING, TRIM, REPLACE, REVERSE, INDEX_OF, LEFT, RIGHT, TOSTRING, STRINGJOIN, STRINGSPLIT
  • Math functions: ABS, CEILING, FLOOR, ROUND, SQRT, POWER, LOG, LOG10, EXP, SIGN, TRUNC, PI, RAND
  • Array functions: ARRAY_LENGTH, ARRAY_SLICE, ARRAY_CONCAT
  • Type checks: IS_STRING, IS_NUMBER, IS_BOOL, IS_ARRAY, IS_OBJECT, IS_INTEGER, IS_PRIMITIVE
  • Named parameters (@name)
  • Client SDK: azure-cosmos Java SDK. Enable TLS (FLOCI_AZ_TLS_ENABLED=true) and point to https://localhost:4577; fetch the runtime cert from GET /_floci/tls-cert and install it into your truststore.
  • Known gaps: JOIN with nested arrays, full-text / vector search, geospatial, multi-region and RU/s governance features.

Non-Goals and Constraints

To prevent configuration errors, note what Floci AZ does not do:

  1. HTTPS (most services): All services run on plain HTTP on port 4577 by default. Do not use DefaultEndpointsProtocol=https unless you have explicitly enabled TLS. For SDKs that require an https:// URL (App Configuration, Key Vault), use a ForceHttp transport policy to rewrite the request back to HTTP before it is sent.
  2. TLS (optional): Set FLOCI_AZ_TLS_ENABLED=true to enable HTTP+HTTPS on the same port 4577 via a protocol-sniffing proxy. A self-signed certificate is generated at runtime and persisted under data/tls/; it regenerates automatically when FLOCI_AZ_HOSTNAME or FLOCI_AZ_BASE_URL changes. Fetch the active certificate PEM from GET /_floci/tls-cert to install it dynamically into your truststore. The Azure Cosmos DB Java SDK requires TLS. Enable this when using it.
  3. No Web UI: There is no dashboard at 4577. It is an API-only emulator.
  4. Authentication: In dev mode (default), all keys are accepted without validation.
  5. Production Scale: Designed for dev/test. Not for high-availability storage.

Community

Join the Floci community on Slack or GitHub Discussions. Feature ideas, compatibility questions, design tradeoffs, and rough proposals are welcome.

Sponsors

Floci is independent open source, funded by the people and companies who use it. Sponsorship buys gratitude and nothing else: every emulated service is free for everyone, forever, and no sponsor gets features, priority, or roadmap influence that the rest of the Flock does not.

🥇 Gold

Large logo with top placement in the emulator READMEs and on floci.io, plus a mention in release notes.

IceGuard · Softmax

🥈 Silver

Logo in the emulator READMEs and on floci.io, plus a mention in release notes.

Your logo here. Become a sponsor.

🥉 Community

Name in the emulator READMEs, a sponsor badge on GitHub, and our sincere thanks.

AutoScout24 · Nexxion AI

Every sponsor, including the Friends of the Flock who support Floci outside these tiers, is listed in THANKS.md.

Sponsor Floci

Star History

Star History Chart

Contributors

Contributors

License

MIT. Use it however you want.

azure
azure-devops
azure-functions
azure-functions-core-tools
azure-service
azure-storage
azurite
docker
emulator
floci
floci-az
testcontainers

floci-io/floci-az

Light, fluffy, and always free - Local Azure Emulator

Java

777

352 commits

updated Oct 19, 2026

See the code

README

Floci Azure Floci Azure

Any Cloud. Locally.
Light, fluffy, and always free
No account. No auth token. No feature gates. Just docker compose up.

Latest Release Build Status Docker Pulls Docker Image Size License: MIT GitHub Stars

What is Floci AZ? · Quick Start · Features · Why Floci AZ? · Services · SDKs · Compatibility · Configuration · Docs


What is Floci AZ?

Floci AZ is a free, open-source local Azure emulator for development, testing, and CI.

It gives you Azure-compatible services on your machine without requiring a cloud account, an auth token, or paid feature gates. Point your Azure SDK, CLI, or Terraform at http://localhost:4577 and keep your existing workflows.

Floci AZ is the Azure member of the Floci emulator family.

EmulatorCloudPort
flociAWS4566
floci-azAzure4577
floci-gcpGCP4588
floci-ociOCI4599

Quick Start

# docker-compose.yml
services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock  # required for Azure Functions
docker compose up

Or run directly:

docker run -d --name floci-az \
  -p 4577:4577 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  floci/floci-az:latest

All services are available at http://localhost:4577. Use any account name and key: SharedKey credentials are not validated.

Azure Functions requires access to the Docker socket so Floci AZ can spawn runtime containers on demand. Mount /var/run/docker.sock as shown above. If you don't use Functions, the socket mount is optional.

TLS (for the Cosmos DB Java SDK)

The Azure Cosmos DB Java SDK enforces TLS in gateway mode. Enable the built-in TLS proxy to serve HTTP and HTTPS on the same port:

# docker-compose.yml
services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./data:/app/data        # persist generated cert across restarts
    environment:
      FLOCI_AZ_TLS_ENABLED: "true"
      FLOCI_AZ_HOSTNAME: floci-az   # add Docker service name to cert SANs

The self-signed certificate is generated at startup and cached under data/tls/. Fetch it at runtime from GET http://localhost:4577/_floci/tls-cert to install it into your truststore: no static cert to bundle or import manually.

Terraform / OpenTofu (azurerm) also requires TLS. The provider discovers the cloud over HTTPS (GET https://<host>/metadata/endpoints), so it fails against plain HTTP. See the Terraform / OpenTofu guide.

Features

Local Azure without the cloud account

Run Azure-compatible services locally without an Azure account, auth token, or paid feature gates.

Real Docker where fidelity matters

Azure Functions, Event Hubs, and Cosmos DB engine APIs (MongoDB, PostgreSQL, Cassandra, Gremlin) use real Docker-backed execution instead of shallow mocks.

Drop-in Azure SDK compatibility

Point standard Azure SDK clients at http://localhost:4577. Existing connection strings, credentials, and SDK workflows stay unchanged.

Fast enough for CI

The native image starts in milliseconds and keeps idle memory low, making it practical for local development and test pipelines.

Configurable persistence

Choose from in-memory, persistent, hybrid, and write-ahead log storage depending on the durability profile you need.

Why Floci AZ?

Floci AZ gives you more services than the official local tools, consolidated on a single port, with a native image that starts in milliseconds.

FeatureFloci AZAzuriteFunctions Core Tools
Blob Storage✅✅❌
Queue Storage✅✅❌
Table Storage✅✅❌
Azure Functions✅❌✅
App Configuration✅❌❌
Cosmos DB (SQL API)✅❌❌
Key Vault✅❌❌
Event Hubs✅❌❌
Service Bus✅❌❌
Azure SQL Database✅❌❌
Azure DB for PostgreSQL✅❌❌
AKS (Kubernetes)✅❌❌
Container Apps✅❌❌
API Management✅❌❌
Virtual Machines✅❌❌
Azure Cache for Redis✅❌❌
Container Registry✅❌❌
Container Instances✅❌❌
Event Grid✅❌❌
Azure Monitor / Logs✅❌❌
Communication Email✅❌❌
Managed Identity✅❌❌
Azure Policy✅❌❌
Microsoft Entra ID✅❌❌
Microsoft Graph✅❌❌
Native binary✅❌✅
Unified port✅ (4577)❌❌
Storage modes✅ (persistent/WAL/Hybrid)❌❌
Startup time<100ms (native image)ModerateFast
LicenseMITMITMIT
Azure Cosmos DB Emulator vs Floci AZ

What is the Azure Cosmos DB Emulator?

The Azure Cosmos DB Emulator is Microsoft's official local emulator for Cosmos DB. It ships as a Windows installer or a Windows-container Docker image, exposes a built-in Data Explorer UI, and supports multiple Cosmos DB APIs (SQL, MongoDB, Cassandra, Gremlin, Table). It is a faithful replica of the cloud service, but it carries the full weight of that fidelity.

Head-to-head

FeatureAzure Cosmos DB EmulatorFloci AZ
PlatformWindows-first (Windows containers historically required)Linux-native containers: runs on Mac, Linux, and Windows
Docker image sizeHeavy (~GBs depending on version/base image)Lightweight modular engines (~50 MB to a few hundred MB depending on selected APIs)
Startup timeSlow startup (tens of seconds)On-demand startup: only starts the required Cosmos API engine
RAM requiredHigh memory usage (commonly ≥ 2 GB)Minimal footprint: only active engines consume resources
Cosmos DB APIsSQL (NoSQL), MongoDB, Cassandra, Gremlin, TableSQL (NoSQL), MongoDB, PostgreSQL, Cassandra, Gremlin, Table
Cosmos API implementationMicrosoft proprietary emulatorAPI-specific compatibility engines
NoSQL / SQL API providerNative Cosmos Emulator🟢 Embedded in-process engine: full SQL dialect, no Docker, instant startup
MongoDB API providerNative Cosmos Emulator🟢 MongoDB Community Server: identical wire protocol (BSON + OP_MSG)
PostgreSQL API providerNative Cosmos Emulator🟢 Citus (the exact engine Azure runs): standard JDBC driver, zero code changes
Cassandra API providerNative Cosmos Emulator🟢 ScyllaDB: CQL-compatible, same DataStax driver
Gremlin API providerNative Cosmos Emulator🟡 Apache TinkerPop: standard traversals work; Cosmos extensions not emulated
Table API providerNative Cosmos Emulator🟢 In-memory (embedded): same azure-data-tables SDK, no Docker
Other Azure servicesCosmos DB onlyBlob · Queue · Table · Functions · App Config · Cosmos DB in a unified local Azure stack
HTTPS / certificatesSelf-signed certificates required: must be imported into the OS/JVM trust store or validation disabledPlain HTTP on 4577 by default. Optional TLS: set FLOCI_AZ_TLS_ENABLED=true, and HTTP and HTTPS are served on the same port 4577 via protocol-sniffing proxy; self-signed cert generated at runtime, no static cert bundled, cert available at GET /_floci/tls-cert
Web UI / Data Explorer✅ Built-in❌ API-focused local development environment
Open source❌ Proprietary✅ MIT
CI/CD friendliness⚠️ Heavy images and slower pipelines✅ Fast startup and Linux-friendly containers
Startup modelStarts the full emulator stackStarts only the requested Cosmos API engine
Container strategyMonolithic emulatorModular provider-based architecture
Cloud abstraction philosophyCosmos-specific emulatorUnified cloud abstraction through floci
Primary goalOfficial local Cosmos emulatorLightweight Azure-compatible local development and integration testing
Behavioral parityHigher Azure-specific behavior parityHigh protocol/API compatibility, not full Azure infrastructure emulation
RU/s and global distributionPartial simulation❌ Not fully emulated
Multi-region replicationPartial support❌ Not emulated
Consistency semanticsAzure-orientedBest-effort compatibility depending on engine
Recommended usageFull local Cosmos-focused workflowsFast local development, testing, CI/CD, and lightweight Azure integration workflows

Floci AZ does not aim to fully reproduce Azure Cosmos DB internals or cloud infrastructure behavior.

The goal is to provide high protocol and SDK compatibility through API-specific local engines optimized for:

  • local development
  • integration testing
  • CI/CD pipelines
  • lightweight developer environments

Each Cosmos API is backed by the engine that most closely matches its protocol and driver behavior.

Exact Azure features such as:

  • RU/s throughput semantics
  • global distribution
  • multi-region replication
  • autoscaling
  • exact consistency guarantees
  • Azure internal infrastructure behavior

are intentionally considered out of scope.

When to choose which

Use the official emulator when you need:

  • Full fidelity with the Cosmos DB wire protocol and advanced features (stored procedures, triggers, change feed, TTL, RU/s governance, and multi-region topology simulation).
  • The Data Explorer UI for manual data inspection.

Use Floci AZ when you need:

  • A lightweight, cross-platform dev/test environment that starts in milliseconds.
  • CI/CD pipelines on Linux runners (GitHub Actions, GitLab CI, CircleCI, etc.).
  • Multiple Azure services in a single container: no juggling separate emulators.
  • No TLS certificate headaches.
  • Cosmos DB SQL API coverage is sufficient (CRUD, SQL queries, PATCH, transactional batch, pagination, aggregates, string functions).

Architecture Overview

flowchart LR
    Client["Azure SDK / CLI"]

    subgraph FlociAz ["floci-az, port 4577"]
        Router["HTTP Router\nJAX-RS / Vert.x\nprotocol-sniffing TLS proxy"]

        subgraph Stateless ["Stateless Services"]
            A["App Configuration · Key Vault\nAPI Management · Event Grid\nVirtual Network · Virtual Machines\nContainer Instances · Monitor / Log Analytics\nCommunication Email\nManaged Identity · Azure Policy · Microsoft Entra ID · Microsoft Graph · ARM management plane"]
        end

        subgraph Stateful ["Stateful Services"]
            B["Blob · Queue · Table\nCosmos DB (NoSQL)"]
        end

        subgraph Containers ["Container Services"]
            C["Azure Functions\nEvent Hubs\nService Bus\nAzure SQL\nAKS\nAzure Cache for Redis\nContainer Registry"]
            D["Cosmos engines\nmongo · citus · scylla · gremlin"]
        end

        Router --> Stateless
        Router --> Stateful
        Router --> Containers
        Stateless & Stateful --> Store[("StorageBackend\nmemory · hybrid · persistent · wal")]
    end

    Docker["Docker Engine"]
    Client -->|"HTTP/HTTPS :4577\nAzure wire protocol"| Router
    Containers -->|"Docker API\nsidecars & function containers"| Docker

Supported Services

ServiceRoutingNotable operations
Blob Storage/{account}/Create/delete containers, upload/download/delete blobs, list blobs; ADLS Gen2 DFS filesystem/path operations with Hadoop ABFS 3.3.4 compatibility; user delegation key/SAS
Azure SignalR Service/server/, /client/, *.service.signalr.netDefault mode over WebSockets; ASP.NET Core hubs, JSON/MessagePack, groups, users, and broadcasts. Per-account isolation through {account}.service.signalr.net hostnames
Queue Storage/{account}-queue/Create/delete queues, send/receive/peek/delete messages, visibility timeout
Table Storage/{account}-table/Create/delete tables, insert/get/update/upsert/delete entities; OData $filter / $select / $top; server-side pagination (continuation tokens); ETag optimistic concurrency; Entity Group Transactions ($batch)
Azure Functions/{account}-functions/Deploy & invoke HTTP-triggered functions (node, python, java, dotnet); warm-container pool
App Configuration/{account}-appconfig/Key-values, labels, feature flags, snapshots (async provisioning), revisions, locks, ETags; pagination (@nextLink), $select, tags filtering, Accept-Datetime time-travel, Sync-Token
Cosmos DB (NoSQL)/{account}-cosmos/Databases, containers, documents CRUD + full SQL queries: always-on, no Docker. PATCH; transactional batch.
Cosmos DB NoSQL (embedded)/{account}-cosmos-nosql/Same embedded SQL engine as above, exposed as a named engine endpoint. Opt-in with FLOCI_AZ_SERVICES_COSMOS_ENGINES_NOSQL_ENABLED=true; no Docker required.
Key Vault/{account}-keyvault/Self-signed certificates with PFX/PEM secrets; Secrets CRUD, versioning, soft-delete, properties update; Keys CRUD, backup/restore, rotation, RSA/EC/oct crypto (encrypt/decrypt/sign/verify/wrap/unwrap), /rng; Managed HSM (/{account}-managedhsm/)
Event HubsAMQP :5672 / Kafka :9093AMQP 1.0 (Artemis sidecar), Kafka-compatible (Redpanda, opt-in)
Service Bus/{account}-servicebus/ + AMQP :5673Queues, topics, subscriptions (created dynamically); AMQP 1.0 data plane via Artemis sidecar, or mocked (management plane only)
Azure SQL DatabaseARM path + /{account}-sql/Servers, databases, firewall rules; ARM-only by default, optional managed SQL Server 2025 containers
Azure Database for PostgreSQLARM path (Microsoft.DBforPostgreSQL) + /{account}-postgres/Flexible servers, databases, firewall rules, configurations; Docker-backed postgres:17-alpine containers (no EULA), dynamic port allocation, or mocked
Azure Database for MySQLARM path (Microsoft.DBforMySQL) + /{account}-mysql/Flexible servers, databases, firewall rules, configurations; Docker-backed mysql:8.0 containers (no EULA), dynamic port allocation, or mocked
Azure Database for MariaDBARM path (Microsoft.DBforMariaDB) + /{account}-mariadb/Servers (single-server model), databases, firewall rules, configurations; Docker-backed mariadb:10.11 containers (no EULA), dynamic port allocation, or mocked
Azure Kubernetes ServiceARM path (Microsoft.ContainerService)CreateOrUpdate, Get, Delete, List, agent pools, kubeconfig (listClusterAdminCredential); real k3s containers or mocked
Azure Container AppsARM path (Microsoft.App) + environment-specific app FQDNManaged environment/app CRUD, Single/Multiple revisions, secrets, min/max replicas, Docker-backed HTTP ingress or mocked
API ManagementARM path (Microsoft.ApiManagement) + /{account}-apim/{service}/In-process APIM emulator for ARM resources, gateway routing, products/subscriptions, named values, backends, OpenAPI import, and a focused policy subset
Virtual NetworkARM path (Microsoft.Network)VNet, subnet, NIC, public IP, NSG, private DNS zone (+ virtual network links, record sets), private endpoint (+ private DNS zone groups), and private link service ARM resources; subnet listing is scoped to the parent VNet; NIC private IPs are synthesized for VM/Terraform compatibility
Virtual MachinesARM path (Microsoft.Compute)VM lifecycle (create/start/stop/deallocate/restart/delete/list), instanceView power state; mocked by default (no Docker), or one Linux container per VM with mocked: false
Azure Cache for RedisARM path (Microsoft.Cache)Cache CRUD, listKeys/regenerateKey; real valkey/valkey:8-alpine containers (data plane, primary key as password) or mocked; non-SSL port
Azure Container RegistryARM path (Microsoft.ContainerRegistry)Registry CRUD, listCredentials/regenerateCredential, checkNameAvailability; one shared registry:2 (Docker Registry V2 push/pull, anonymous on its published port); az acr login through the Entra token exchange on {name}.azurecr.io; or mocked
Azure Container InstancesARM path (Microsoft.ContainerInstance)Container group lifecycle (create/update/delete/list by rg + subscription), start/stop/restart with spec-exact LRO shapes, container logs, instanceView, azurerm-safe read-backs (ports/resources always present, canonical enum casing, secrets never echoed); real Docker containers with shared-netns pod semantics (localhost between group members) or mocked
Event GridARM path (Microsoft.EventGrid) + /{topic}-eventgrid/api/eventsCustom Topics, listKeys/regenerateKey, webhook eventSubscriptions with subject/eventType filters; publish in Event Grid + CloudEvents 1.0 schemas; async webhook delivery with retry; SubscriptionValidationEvent handshake; HTTP-only (no sidecar)
Azure Monitor / Log AnalyticsARM path (Microsoft.OperationalInsights / Microsoft.Insights) + /dataCollectionRules/{id}/streams/{stream} + /v1/workspaces/{id}/queryWorkspaces, Data Collection Endpoints/Rules; Logs Ingestion API; Log Analytics query with a KQL subset (where/project/take/limit + timespan); HTTP-only (no sidecar)
Communication Services Email/emails:send + /emails/operations/{id} + /emailMessages + ARM path (Microsoft.Communication)ACS Email send + status polling; in-memory inspection mailbox (Mailpit-style GET /emailMessages); communication/email services + domains via ARM; captures messages locally, no real delivery; HTTP-only (no sidecar)
Managed IdentityARM path (Microsoft.ManagedIdentity) + /metadata/identity/oauth2/tokenUser-assigned identities (server-generated principalId/clientId), federated identity credentials, system-assigned identities/default; IMDS token endpoint for ManagedIdentityCredential (point the SDK at the emulator with AZURE_POD_IDENTITY_AUTHORITY_HOST); v1.0 JWTs signed with the Entra key, verifiable via JWKS; HTTP-only (no sidecar)
Azure PolicyARM path (Microsoft.Authorization/policy*)Policy definitions, set definitions (initiatives), assignments and exemptions at management-group, subscription, resource-group and resource scope; $filter scope forms (atScope(), atExactScope(), atScopeAndBelow()); server-side scope, instanceId, definitionVersion, audit metadata and assignment identities; referential integrity on delete. Control plane only: rules are stored, never evaluated, and no built-ins are seeded; HTTP-only (no sidecar)
API Management details

Floci AZ includes an in-process API Management emulator intended for local development, SDK compatibility tests, and CI workflows that need APIM-shaped ARM resources plus a lightweight gateway. It is not a full Azure APIM gateway implementation.

APIM is available through:

  • ARM-compatible resource paths under Microsoft.ApiManagement.
  • Gateway routes under /{account}-apim/{serviceName}/{apiPath...}. With the default account this is http://localhost:4577/devstoreaccount1-apim/{serviceName}/....

Supported

  • Management service resources: create, get, list, delete.
  • API resources: create, get, list, delete.
  • Operation resources: create, get, list, delete.
  • Policy resources at service, API, and operation scope.
  • Product resources and product-to-API links.
  • Subscription resources with gateway subscription-key enforcement.
  • Named values, including secret named values whose properties.value is not exposed in ARM responses.
  • Backends and <set-backend-service backend-id="...">.
  • OpenAPI JSON import for APIs, including operation generation from paths.
  • OpenAPI reimport behavior that replaces previous generated operations.
  • Gateway route matching for API paths and operation URL templates.
  • Basic backend proxying when an API serviceUrl or backend policy is configured.

Supported Policy Subset

The policy engine intentionally supports a focused subset:

  • <set-header> with exists-action="override", skip, append, and delete.
  • <set-query-parameter> with exists-action="override", skip, and delete.
  • <rewrite-uri template="...">.
  • <set-backend-service base-url="...">.
  • <set-backend-service backend-id="...">.
  • <return-response>.
  • <set-status code="..."> inside return-response.
  • <set-body> inside return-response.
  • Named value interpolation with {{name}} in supported policy values.

Partial or Out of Scope

The APIM emulator is intentionally scoped. These features are not fully emulated:

  • The full APIM policy language and C# policy expressions.
  • JWT validation, OAuth/OIDC flows, certificates, mTLS, and managed identities.
  • API revisions, API versions, version sets, releases, tags, groups, users, loggers, diagnostics, named value Key Vault references, and developer portal behavior.
  • APIM networking, private endpoints, custom domains, DNS, scale units, regions, SKU behavior, and deployment lifecycle timing.
  • Exact APIM error formats, tracing, analytics, caching, rate-limit counters, quota counters, and distributed gateway behavior.

The current goal is practical local parity for common APIM provisioning and gateway tests, not full Azure infrastructure simulation.

Real Docker Integration

Floci AZ uses real Docker containers when in-process emulation would reduce fidelity.

ServiceDefault imageWhat is real
Azure Functionsmcr.microsoft.com/azure-functions/<runtime>Real Azure Functions runtime, warm container pool
Event Hubs AMQPapache/activemq-artemisFull AMQP 1.0 broker
Event Hubs Kafkaredpandadata/redpandaKafka-compatible broker (opt-in)
Cosmos DB MongoDBmongo:7MongoDB Community Server, full wire protocol
Cosmos DB PostgreSQLcitusdata/citusCitus: the exact engine Azure runs
Cosmos DB Cassandrascylladb/scylla:6.2CQL-compatible drop-in
Cosmos DB Gremlintinkerpop/gremlin-serverApache TinkerPop: standard Gremlin traversals
Azure SQL Databasemcr.microsoft.com/mssql/server:2025-latestOptional managed SQL Server engine (per server)
Azure Database for PostgreSQLpostgres:17-alpinePostgreSQL engine (per flexible server)
Azure Database for MySQLmysql:8.0MySQL engine (per flexible server)
Azure Database for MariaDBmariadb:10.11MariaDB engine (per server)
AKSrancher/k3s:latestKubernetes API server via k3s
Azure Container AppsUser-provided imagesRevision replicas with HTTP ingress through floci-az
Azure Cache for Redisvalkey/valkey:8-alpineRedis / Valkey protocol (per cache)
Azure Container Registryregistry:2OCI-compatible registry for docker push and docker pull (shared)

Docker-backed services require the Docker socket:

docker run -d --name floci-az \
  -p 4577:4577 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  floci/floci-az:latest

The Cosmos DB multi-API engines (MongoDB, PostgreSQL, Cassandra, Gremlin, plus the embedded NoSQL and Table engines) are disabled by default and configured separately: see the Cosmos DB engine configuration docs.

Persistence and Storage Modes

Floci AZ features the same flexible storage architecture as Floci. Configure the storage mode globally via FLOCI_AZ_STORAGE_MODE or override it per service.

ModeBehaviorBest for...Durability
memory (Default)Entirely in-RAM. Data is lost when the container stops.Speed, ephemeral testing, CI pipelines.❌ None
persistentData is loaded at startup and flushed to disk on graceful shutdown.Simple local dev with state preservation.⚠️ Medium
hybridIn-memory performance with periodic async flushing (every 5s).The perfect balance of speed and safety.✅ Good
walWrite-Ahead Log. Every mutation is logged to disk before responding.Maximum durability for critical state.💎 Highest

[!TIP] Use hybrid for a "it just works" experience that survives container restarts. For ephemeral integration tests where state doesn't matter, keep the default memory mode for maximum performance.

SDK Integration

Floci AZ uses path-style routing:

ServiceEndpointNotes
Blobhttp://localhost:4577/{accountName}
Data Lake Storage Gen2http://localhost:4577/{accountName}Use the {accountName}.dfs.core.windows.net Host header; maps to the Blob backend and supports Hadoop ABFS 3.3.4 filesystem/path flows, including HNS detection, conditional create/overwrite, properties/XAttrs, ACL metadata, leases, append/flush, listing, status, rename, and delete
Queuehttp://localhost:4577/{accountName}-queue
Tablehttp://localhost:4577/{accountName}-table
Functionshttp://localhost:4577/{accountName}-functions
App Configurationhttp://localhost:4577/{accountName}-appconfigSome SDKs require an https:// URL: use a ForceHttp transport policy to rewrite to HTTP
Cosmos DBhttp://localhost:4577/{accountName}-cosmosPython / Node SDKs. Java SDK: enable TLS (FLOCI_AZ_TLS_ENABLED=true) and use https://localhost:4577: the SDK enforces TLS; cert auto-generated at runtime, fetch from GET /_floci/tls-cert
Key Vaulthttp://localhost:4577/{accountName}-keyvaultSome SDKs require an https:// URL: use a ForceHttp transport policy to rewrite to HTTP
Event HubsAMQP amqp://localhost:5672 · Kafka localhost:9093

The standard development storage connection string works out of the box:

DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://localhost:4577/devstoreaccount1;QueueEndpoint=http://localhost:4577/devstoreaccount1-queue;TableEndpoint=http://localhost:4577/devstoreaccount1-table;
Python
# azure-storage-blob
from azure.storage.blob import BlobServiceClient

conn_str = (
    "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;"
    "AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;"
    "BlobEndpoint=http://localhost:4577/devstoreaccount1;"
)

client = BlobServiceClient.from_connection_string(conn_str)
client.create_container("my-container")

blob = client.get_container_client("my-container").get_blob_client("hello.txt")
blob.upload_blob(b"Hello from floci-az!")
print(blob.download_blob().readall())
# azure-storage-queue
from azure.storage.queue import QueueServiceClient

conn_str = (
    "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;"
    "AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;"
    "QueueEndpoint=http://localhost:4577/devstoreaccount1-queue;"
)

client = QueueServiceClient.from_connection_string(conn_str)
queue = client.create_queue("my-queue")
queue.send_message("Hello from floci-az!")
print(list(queue.receive_messages())[0].content)
# azure-data-tables
from azure.data.tables import TableServiceClient

conn_str = (
    "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;"
    "AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;"
    "TableEndpoint=http://localhost:4577/devstoreaccount1-table;"
)

service = TableServiceClient.from_connection_string(conn_str)
table = service.create_table("MyTable")
table.create_entity({"PartitionKey": "pk1", "RowKey": "rk1", "Value": "hello"})
print(table.get_entity("pk1", "rk1")["Value"])
Java
BlobServiceClient client = new BlobServiceClientBuilder()
    .connectionString(
        "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;" +
        "AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;" +
        "BlobEndpoint=http://localhost:4577/devstoreaccount1;")
    .buildClient();

client.createBlobContainer("my-container");

BlobClient blob = client.getBlobContainerClient("my-container").getBlobClient("hello.txt");
blob.upload(new ByteArrayInputStream("Hello from floci-az!".getBytes()), 20);
Node.js / TypeScript
import { BlobServiceClient } from "@azure/storage-blob";

const CONN =
  "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;" +
  "AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;" +
  "BlobEndpoint=http://localhost:4577/devstoreaccount1;";

const client = BlobServiceClient.fromConnectionString(CONN);
const { containerClient } = await client.createContainer("my-container");

const blob = containerClient.getBlockBlobClient("hello.txt");
await blob.upload(Buffer.from("Hello from floci-az!"), 20);
console.log((await blob.downloadToBuffer()).toString());
Azure Functions

Functions are managed via a REST management API and invoked over HTTP. The emulator spawns a real Azure Functions runtime container on first invoke and keeps it warm for subsequent calls.

BASE="http://localhost:4577/devstoreaccount1-functions"

# Create a function app
curl -s -X PUT "$BASE/admin/apps/my-app" \
  -H "Content-Type: application/json" \
  -d '{"runtime":"node","environment":{"MY_VAR":"hello"}}'

# Deploy a function (ZIP of your function code, base64-encoded)
ZIP_B64=$(base64 < my-function.zip)
curl -s -X PUT "$BASE/admin/apps/my-app/functions/hello" \
  -H "Content-Type: application/json" \
  -d "{\"handler\":\"index.handler\",\"timeoutSeconds\":60,\"zipBase64\":\"$ZIP_B64\"}"

# Invoke
curl "$BASE/api/my-app/hello?msg=world"

Supported runtimes: node, python, java, dotnet.

To select a Linux language version, pass the Azure-compatible linuxFxVersion. For example, Python 3.12 uses {"runtime":"python","linuxFxVersion":"Python|3.12"}.

Azure CLI (azfloci)

azfloci is a companion CLI that acts as a transparent proxy for the official Azure CLI (az). It automatically injects the correct connection strings and disables SSL verification so you can use standard az commands against the local emulator.

# Optional: alias azfloci as az for a seamless experience
alias az='python3 /path/to/floci-az/azfloci/azfloci.py'

# Initialize or get connection string info
az setup

# Blob Storage
az storage container create --name my-container
az storage blob upload --container-name my-container --name hello.txt --file hello.txt
az storage blob list --container-name my-container --output table

# Queue Storage
az storage queue create --name my-queue
az storage message put --queue-name my-queue --content "Hello from CLI"

# Table Storage
az storage table create --name MyTable

azfloci automatically detects --account-name (defaulting to devstoreaccount1) and constructs the appropriate local endpoint.

When your app runs in a separate container

Set the service name as the hostname so returned URLs resolve correctly inside Docker Compose:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - app-net

  my-app:
    environment:
      AZURE_BLOB_ENDPOINT: http://floci-az:4577/devstoreaccount1
      AZURE_QUEUE_ENDPOINT: http://floci-az:4577/devstoreaccount1-queue
      AZURE_TABLE_ENDPOINT: http://floci-az:4577/devstoreaccount1-table
    depends_on:
      floci-az:
        condition: service_healthy
    networks:
      - app-net

networks:
  app-net:

Compatibility Testing

The compatibility-tests directory validates Floci AZ across SDKs and tooling workflows. Each directory is one suite. App Configuration, Key Vault, Event Hubs, and Service Bus are exercised inside the SDK suites rather than as standalone modules.

ModuleLanguage / ToolCoverage
sdk-test-pythonPython 3Blob, Queue, Table, Cosmos, App Configuration, Key Vault, ACR, Redis, VM, Managed Identity
sdk-test-javaJava 21Storage, Cosmos (+ Mongo/PostgreSQL/Cassandra/Gremlin/Table/NoSQL engines), App Config, Key Vault, Event Hubs, Service Bus, Functions, Container Apps, API Management, SQL, PostgreSQL (Flexible Server), Managed Identity, Policy
sdk-test-nodeNode.jsApp Configuration, Blob, Cosmos, Event Hubs, Key Vault, Queue, Table, Service Bus, Entra ID, Managed Identity
sdk-test-dotnet.NETBlob service SAS, Cosmos (+ bracket properties, point partition, transactional batch), Key Vault (+ certificates, timestamps), Service Bus (+ lock renewal, metadata, peek-lock), SignalR. The only suite covering SignalR
sdk-test-cpp †C++ 17Blob, Queue: Lifecycle plus the bodyless-error path no other SDK reproduces
compat-terraformTerraformazurerm provider apply/destroy (resource group, storage, key vault, VNet, VM, Redis, ACR)
compat-opentofuOpenTofuSame azurerm suite via tofu, plus PostgreSQL Flexible Server (server + database)
compat-azcli ‡Azure CLIaz against a custom cloud with Entra service-principal login

† Built from source via vcpkg, so the image takes ~6 min cold (seconds if warm).

‡ Ships with the Entra ID feature (#23).

Run the suites against a running container:

make test-python-compat
make test-java-compat
make test-node-compat
make test-cpp-compat
make test-cosmos-all    # Cosmos engine tests: MongoDB · PostgreSQL · Cassandra · Gremlin · Table · NoSQL (requires Docker)
make test-iac-compat    # Terraform + OpenTofu
make compat-docker      # full matrix

Migrating from Azurite

Azurite users can point their existing connection strings at Floci AZ with a single endpoint change.

# Before (Azurite default)
DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02...;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;

# After (Floci AZ, single port)
DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02...;BlobEndpoint=http://localhost:4577/devstoreaccount1;QueueEndpoint=http://localhost:4577/devstoreaccount1-queue;TableEndpoint=http://localhost:4577/devstoreaccount1-table;

The account name and key are the same. Floci AZ consolidates all services onto port 4577: no more separate ports per service.

Image Tags

All images are native (multi-arch linux/amd64 + linux/arm64).

ChannelStandardCompat with Azure CLI and azfloci
Release, floatinglatestlatest-compat
Release, pinnedx.y.zx.y.z-compat
Nightly, floatingnightlynightly-compat
Nightly, datednightly-mmddyyyynightly-mmddyyyy-compat

Use latest for stable releases, a pinned version for reproducible builds, and nightly to track main.

image: floci/floci-az:latest         # recommended
image: floci/floci-az:latest-compat  # includes Azure CLI and azfloci
image: floci/floci-az:x.y.z          # pinned release
image: floci/floci-az:nightly        # track main

Release train

Stable releases ship on the 15th and the last day of each month, cut automatically at 00:30 US Central time. Between trains, floci/floci-az:nightly tracks main. Every merged fix is available the next day, and dated nightly-mmddyyyy tags let you pin a specific night's build.

Versions are derived from Conventional Commits by semantic-release; CHANGELOG.md is generated, never hand-edited. Releases are cut from main only: there are no maintenance branches.

Configuration

All settings are overridable via environment variables (FLOCI_AZ_ prefix).

VariableDefaultDescription
FLOCI_AZ_PORT4577Port exposed by the API
FLOCI_AZ_BASE_URLhttp://localhost:4577Base URL used when the emulator returns service URLs
FLOCI_AZ_HOSTNAMEUnsetHostname added to returned URLs and TLS cert SANs when running inside Docker Compose
FLOCI_AZ_TLS_ENABLEDfalseEnable HTTP+HTTPS on the same port via protocol-sniffing proxy
FLOCI_AZ_PARITYcompatHow closely the ARM platform answers follow Azure: compat keeps every response as floci-az has always given it, azure gives Azure's answers (resource-group update and cascading delete, listed subscriptions), strict adds Azure's refusals (unknown subscription or resource group). See the ARM docs
FLOCI_AZ_STORAGE_MODEmemoryStorage mode: memory, persistent, hybrid, or wal
FLOCI_AZ_STORAGE_PATH/app/dataDirectory used for persisted state
FLOCI_AZ_DOCKER_DOCKER_HOSTunix:///var/run/docker.sockDocker socket used to spawn function and sidecar containers
FLOCI_AZ_DOCKER_ENDPOINT_MODEautoHow sidecar containers are addressed: auto (container name or IP and internal port inside Docker, localhost and the published port otherwise) or published (the Docker daemon's host and the published port, for remote daemons such as docker-in-docker or kubedock)
FLOCI_AZ_DOCKER_RESOURCE_NAMESPACE(unset)Namespace inserted into the name of every container and volume floci-az creates (floci-az-<ns>-...) and added as the floci_namespace label, so parallel emulator instances on one Docker host don't collide

Per-service enable flags (FLOCI_AZ_SERVICES_<SERVICE>_ENABLED), TLS certificate paths, Cosmos engine settings, and the rest are documented in the full reference.

Full reference: configuration docs

Per-service storage override

You can set a different storage mode for each service independently:

# docker-compose.yml
environment:
  FLOCI_AZ_STORAGE_MODE: memory
  FLOCI_AZ_STORAGE_SERVICES_BLOB_MODE: wal

Multi-container Docker Compose

When your application runs in a separate container, use the service name as the hostname so returned URLs (such as blob/queue/table endpoints) resolve correctly:

services:
  floci-az:
    image: floci/floci-az:latest
    ports:
      - "4577:4577"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock  # required for Azure Functions
    networks:
      - app-net

  my-app:
    environment:
      AZURE_BLOB_ENDPOINT: http://floci-az:4577/devstoreaccount1
      AZURE_QUEUE_ENDPOINT: http://floci-az:4577/devstoreaccount1-queue
      AZURE_TABLE_ENDPOINT: http://floci-az:4577/devstoreaccount1-table
      AZURE_FUNCTIONS_ENDPOINT: http://floci-az:4577/devstoreaccount1-functions
      AZURE_APPCONFIG_ENDPOINT: https://floci-az:4577/devstoreaccount1-appconfig  # https required by App Config SDK (use ForceHttp transport in your client)
    depends_on:
      floci-az:
        condition: service_healthy
    networks:
      - app-net

networks:
  app-net:

For the Cosmos DB multi-API engines (MongoDB, PostgreSQL, Cassandra, Gremlin, and the embedded NoSQL and Table engines), including enable flags, image/port overrides, the /connect endpoint, and SDK examples, see the Cosmos DB engine configuration docs.

Cosmos DB API parity rationale

Each engine's compatibility level is determined by how closely the underlying runtime matches what Azure Cosmos DB actually runs in production.


🟢 PostgreSQL API: very high parity

Azure Cosmos DB for PostgreSQL is Citus, a distributed PostgreSQL extension developed by the same team that runs inside Azure. The wire protocol, query language, and drivers are identical to vanilla PostgreSQL.

  • Client SDK: standard PostgreSQL JDBC driver (org.postgresql:postgresql), the same driver you use in production, unchanged. Official quickstart.
  • Engine: citusdata/citus Docker image (the exact same project).
  • Known gaps: Azure-specific HA/scaling, multi-region replication, and Azure RBAC are infrastructure features with no local equivalent.
  • Note: Microsoft is retiring this API. The recommended migration path is Azure Database for PostgreSQL (Elastic Clusters) or Cosmos DB for NoSQL.

🟢 MongoDB API: very high parity

Azure Cosmos DB for MongoDB exposes the full MongoDB wire protocol (BSON + OP_MSG). Connecting with any MongoDB driver targets the same binary framing and command set regardless of whether the server is a real mongod or the Azure Cosmos service.

  • Client SDK: any MongoDB driver (mongodb-driver-sync, pymongo, mongodb Node.js package), and the connection string format is identical.
  • Engine: mongo:7 Community Server, the reference implementation of the protocol.
  • Known gaps: Azure-specific index types (wildcard compound), $lookup with let in some API versions, and RU/s throughput governance.

🟢 Table API: high parity

The Azure Table Storage REST API is a straightforward OData/JSON HTTP API. floci-az implements it directly in-process, with no Docker required. Because the protocol is pure HTTP with a well-documented spec, compatibility is structural: the same SDK targets the same URLs and receives the same JSON shapes.

  • Client SDK: azure-data-tables SDK for Java, Python, Node.js, .NET. Use the official Cosmos DB for Table pattern: .endpoint() + AzureNamedKeyCredential. See Java quickstart. The connection string format is also supported for backward compatibility.
  • Engine: in-memory (ConcurrentHashMap), instant startup, zero Docker overhead.
  • Supported query operators: OData eq, ne, gt, ge, lt, le, and, or, not; $filter, $top, $select.
  • Known gaps: Cosmos DB RU/s throughput model, TTL-based expiry, server-side pagination continuation tokens beyond $top.

🟢 Cassandra API: high parity

Azure Cosmos DB for Cassandra implements the Apache Cassandra CQL binary wire protocol (native transport, port 9042). Any CQL-compatible driver connects transparently. ScyllaDB is a CQL-compatible drop-in replacement that shares the same driver ecosystem.

  • Client SDK: DataStax Java Driver (com.datastax.oss:java-driver-core), cassandra-driver-core, or any CQL v4 client. The contact point and port are all you need to change.
  • Engine: scylladb/scylla (default) or any Apache Cassandra image via the image override.
  • Known gaps: some Cosmos-specific TTL semantics, Cosmos RBAC, Cassandra LWT (lightweight transactions) edge cases, and ALLOW FILTERING query restrictions differ slightly.

🟡 Gremlin API: medium parity

Azure Cosmos DB for Gremlin is built on Apache TinkerPop. Standard Gremlin traversals work identically. However, Cosmos DB adds proprietary extensions (partition key semantics, bulk executor, certain graph-level operations) that TinkerPop Gremlin Server does not implement.

  • Client SDK: gremlin-driver (org.apache.tinkerpop:gremlin-driver), connecting via WebSocket to port 8182, same as in production.
  • Engine: tinkerpop/gremlin-server.
  • Known gaps: Cosmos DB pk partition key column requirement, addE/addV Cosmos extensions, bulk import API, and multi-region graph consistency guarantees.

🟢 NoSQL / SQL API: very high parity (embedded engine)

Both NoSQL endpoints are in-process, with no Docker and instant startup:

EndpointUse caseSQL queriesDocker
{account}-cosmosCRUD + SQL, always-on✅ Full SQL dialectNo
{account}-cosmos-nosqlNamed engine endpoint, opt-in✅ Full SQL dialectNo

The embedded NoSQL engine implements the Azure Cosmos DB SQL grammar in-process:

  • SELECT, WHERE, ORDER BY, GROUP BY, OFFSET LIMIT, SELECT TOP, SELECT DISTINCT
  • Aggregates: COUNT, SUM, AVG, MIN, MAX
  • Predicates: =, !=, IN, BETWEEN, LIKE, NOT, AND, OR, IS_DEFINED, IS_NULL, CONTAINS, STARTSWITH, ENDSWITH, STRINGEQUALS, REGEXMATCH, ARRAY_CONTAINS
  • Conditional: IIF(condition, trueVal, falseVal)
  • String functions: LOWER, UPPER, LENGTH, CONCAT, SUBSTRING, TRIM, REPLACE, REVERSE, INDEX_OF, LEFT, RIGHT, TOSTRING, STRINGJOIN, STRINGSPLIT
  • Math functions: ABS, CEILING, FLOOR, ROUND, SQRT, POWER, LOG, LOG10, EXP, SIGN, TRUNC, PI, RAND
  • Array functions: ARRAY_LENGTH, ARRAY_SLICE, ARRAY_CONCAT
  • Type checks: IS_STRING, IS_NUMBER, IS_BOOL, IS_ARRAY, IS_OBJECT, IS_INTEGER, IS_PRIMITIVE
  • Named parameters (@name)
  • Client SDK: azure-cosmos Java SDK. Enable TLS (FLOCI_AZ_TLS_ENABLED=true) and point to https://localhost:4577; fetch the runtime cert from GET /_floci/tls-cert and install it into your truststore.
  • Known gaps: JOIN with nested arrays, full-text / vector search, geospatial, multi-region and RU/s governance features.

Non-Goals and Constraints

To prevent configuration errors, note what Floci AZ does not do:

  1. HTTPS (most services): All services run on plain HTTP on port 4577 by default. Do not use DefaultEndpointsProtocol=https unless you have explicitly enabled TLS. For SDKs that require an https:// URL (App Configuration, Key Vault), use a ForceHttp transport policy to rewrite the request back to HTTP before it is sent.
  2. TLS (optional): Set FLOCI_AZ_TLS_ENABLED=true to enable HTTP+HTTPS on the same port 4577 via a protocol-sniffing proxy. A self-signed certificate is generated at runtime and persisted under data/tls/; it regenerates automatically when FLOCI_AZ_HOSTNAME or FLOCI_AZ_BASE_URL changes. Fetch the active certificate PEM from GET /_floci/tls-cert to install it dynamically into your truststore. The Azure Cosmos DB Java SDK requires TLS. Enable this when using it.
  3. No Web UI: There is no dashboard at 4577. It is an API-only emulator.
  4. Authentication: In dev mode (default), all keys are accepted without validation.
  5. Production Scale: Designed for dev/test. Not for high-availability storage.

Community

Join the Floci community on Slack or GitHub Discussions. Feature ideas, compatibility questions, design tradeoffs, and rough proposals are welcome.

Sponsors

Floci is independent open source, funded by the people and companies who use it. Sponsorship buys gratitude and nothing else: every emulated service is free for everyone, forever, and no sponsor gets features, priority, or roadmap influence that the rest of the Flock does not.

🥇 Gold

Large logo with top placement in the emulator READMEs and on floci.io, plus a mention in release notes.

IceGuard · Softmax

🥈 Silver

Logo in the emulator READMEs and on floci.io, plus a mention in release notes.

Your logo here. Become a sponsor.

🥉 Community

Name in the emulator READMEs, a sponsor badge on GitHub, and our sincere thanks.

AutoScout24 · Nexxion AI

Every sponsor, including the Friends of the Flock who support Floci outside these tiers, is listed in THANKS.md.

Sponsor Floci

Star History

Star History Chart

Contributors

Contributors

License

MIT. Use it however you want.

azure
azure-devops
azure-functions
azure-functions-core-tools
azure-service
azure-storage
azurite
docker
emulator
floci
floci-az
testcontainers

Significant stargazers

Ben Younes

442 followers · starred Jul 2026

PatrickJS

3,597 followers · starred Jul 2026

haruna

178 followers · starred Apr 2026

Elie Steinbock

2,672 followers · starred May 2026