Deploy
$99/mo
Join waitlistSingle-node vector map
A managed single-node block stack connected to one vector map node in the cloud environment you choose.
Included features
Mission Statement
Microstacks is a stack management system designed on the Unix philosophy of composition. It virtualizes network addresses to represent a distributed application as a hierarchy of dependencies, thereby eliminating the need for YAML configuration to define service relationships. Virtual addressing keeps application topology stable while the runtime is deployed and scaled across clouds. These capabilities, called federated deployment and vector scaling, establish a new paradigm for stack management.
Swipe sideways to compare columns
Frameworks
MonolithicArchitecture
StaticStructure
CentralizedDeployment
VerticalScaling
Microstacks
ModularArchitecture
Orchestrators
MicroserviceArchitecture
DynamicStructure
DistributedDeployment
HorizontalScaling
A stack is an application organized as paths instead of loose service
names. Use map to place a GitHub project at a domain,
mount to attach frontend dependencies such as an API endpoint,
import to bring services into the root, and link to
connect those services to the blocks that need them.
# Map a GitHub project to a public domain $ stack map github.com/acme/frontend example.com Mapped github.com/acme/frontend at example.com # Mount the frontend API dependency under the domain $ stack mount myorg/api:1.4 example.com/api Mounted /api # Import shared services under the stack root $ stack import mysql:8 example.com/mysql Imported /mysql $ stack import redis:7 example.com/redis Imported /redis # Link services into the API address space $ stack link example.com/mysql example.com/api/mysql Linked /api/mysql to /mysql $ stack link example.com/redis example.com/api/redis Linked /api/redis to /redis # Inspect the live tree $ stack ls -r example.com TYPE PATH IMAGE VECTORS PORTS stack example.com github/acme/front — 443/tcp component example.com/api myorg/api:1.4 — 8080/tcp service example.com/mysql mysql:8 — 3306/tcp service example.com/redis redis:7 — 6379/tcp link example.com/api/mysql example.com/mysql — — link example.com/api/redis example.com/redis — —
Vector scaling is the same operation from another node. SSH into a second cloud, run the same recursive snap, and Microstacks adds another runtime vector without changing the authored stack.
# Open the Azure node console $ ssh ops@azure-eastus.internal Connected to azure-eastus.internal # Run the same command to add a second vector azure$ stack snap -r example.com Snapped example.com on azure-eastus.internal
Federated deployment does not require a new control system for every environment. SSH into a cloud node, run the same snap command, and the complete stack materializes from the shared model on that node.
# Open the AWS node console $ ssh ops@aws-use1.internal Connected to aws-use1.internal # Snap the complete stack onto AWS aws$ stack snap -r example.com Snapped example.com on aws-use1.internal
A complete WordPress stack mapped to wordpress.microstacks.com. Map Caddy as the router, mount WordPress at the root path, import MySQL, and snap the full stack into a local deployment.
# Map Caddy as the router for the WordPress domain
$ stack map \
caddy:2 wordpress.microstacks.com \
-- caddy reverse-proxy --from :80 --to http://127.0.0.1:80
# Mount WordPress at the root path
$ stack mount \
--env=WORDPRESS_DB_HOST=127.0.0.1:3306 \
--env=WORDPRESS_DB_USER=root \
--env=WORDPRESS_DB_PASSWORD=wordpress \
wordpress:7.0.2 wordpress.microstacks.com/
# Import MySQL under /mysql
$ stack import \
--env=MYSQL_DATABASE=wordpress \
--env=MYSQL_ROOT_PASSWORD=wordpress \
mysql:9.7.1 wordpress.microstacks.com/mysql
# Snap the entire stack into a running local deployment
$ stack snap -r wordpress.microstacks.comA local AI workspace mapped to open-webui.microstacks.com. Map Traefik as the router, mount Open WebUI, import Ollama, then run a root-level model block that pulls the model through the linked Ollama service.
# Map Traefik as the router for the Open WebUI domain
$ stack map \
--arguments=--providers.docker=true \
--label 'traefik.http.routers.default.rule=PathPrefix(`/`)' \
--label 'traefik.http.services.default.loadbalancer.server.url=http://127.0.0.1:80' \
traefik:v3.4 open-webui.microstacks.com
# Mount Open WebUI at the root path
$ stack mount \
--env OLLAMA_BASE_URL=http://127.0.0.1:11434 \
ghcr.io/open-webui/open-webui:v0.6.25 \
open-webui.microstacks.com/
# Import Ollama with its default server command
$ stack import \
--env GODEBUG="tlsmlkem=0" \
ollama/ollama:0.32.5 \
open-webui.microstacks.com/ollama
# Add the qwen2.5-0.5b model job at the root path
$ stack import \
--no-restart \
--mask 11434/tcp \
--require 127.0.0.1:11434 \
--env GODEBUG="tlsmlkem=0" \
ollama/ollama:0.32.5 \
open-webui.microstacks.com/qwen2.5-0.5b -- \
ollama pull qwen2.5:0.5b
# Link Ollama into the model address space
$ stack import \
open-webui.microstacks.com/ollama \
open-webui.microstacks.com/qwen2.5-0.5b/ollama
# Snap the Open WebUI stack
$ stack snap -r open-webui.microstacks.comA Redis replica set stack mapped to redis.rs.microstacks.com. Map Caddy as the router, mount RedisInsight, import Redis with instance-aware replica configuration, clone the Redis service block, and snap the primary plus replica vectors.
# Map Caddy as the router for the Redis replica set domain
$ stack map caddy:2 redis.rs.microstacks.com -- \
caddy reverse-proxy --from :80 --to 127.0.0.1:80
# Mount RedisInsight at the root path
$ stack mount \
redis/redisinsight:3.8.0 \
redis.rs.microstacks.com/
# Import Redis with instance-aware primary/replica configuration
$ stack import \
--env 'N=${INSTANCE#1}' \
redis:8.8.1 \
redis.rs.microstacks.com/redis -- \
redis-server \
'${N:+--replicaof}' '${N:+127.0.0.1}' '${N:+6379}'
# Clone the Redis service block under itself
$ stack import \
redis.rs.microstacks.com/redis \
redis.rs.microstacks.com/redis/redis
# Snap RedisInsight and scale the Redis replica vectors
$ stack snap -r redis.rs.microstacks.com
$ stack scale local.redis.rs.microstacks.com/redis=3A Redis cluster stack mapped to redis.cluster.microstacks.com. Map Caddy as the router, mount RedisInsight at the root path, import Redis with cluster ports, clone the Redis service block, and snap each vector into place.
# Map Caddy as the router for the Redis domain
$ stack map caddy:2 redis.cluster.microstacks.com -- \
caddy reverse-proxy --from :80 --to 127.0.0.1:80
# Mount RedisInsight at the root path
$ stack mount \
--env RI_REDIS_HOST=127.0.0.1 --env RI_REDIS_PORT=6379 \
redis/redisinsight:3.8.0 \
redis.cluster.microstacks.com/
# Import the first Redis cluster node
$ stack import \
--endpoint 16379/tcp \
redis:8.8.1 \
redis.cluster.microstacks.com/redis -- \
redis-server --cluster-enabled yes --appendonly yes --cluster-announce-ip \${BIND_ADDR}
# Clone the Redis service block under itself
$ stack import \
redis.cluster.microstacks.com/redis \
redis.cluster.microstacks.com/redis/redis
# Mount a config job to create the Redis cluster
$ stack mount \
--no-restart \
--require 127.0.0.{1..6}:6379 \
redis:8.8.1 \
redis.cluster.microstacks.com/config -- \
redis-cli --cluster create 127.0.0.{1..6}:6379 --cluster-replicas 1 --cluster-yes
# Link Redis into the config address space
$ stack import \
redis.cluster.microstacks.com/redis \
redis.cluster.microstacks.com/config/redis
# Snap RedisInsight and scale the Redis cluster vectors
$ stack snap -r redis.cluster.microstacks.com
$ stack scale local.redis.cluster.microstacks.com/redis=6A MongoDB replica set stack mapped to mongo.rs.microstacks.com. Map Caddy as the router, mount Compass Web, import MongoDB with replica set mode, clone the Mongo service block, and initialize the replica set from a config job.
# Map Caddy as the router for the MongoDB replica set domain
$ stack map caddy:2 mongo.rs.microstacks.com -- \
caddy reverse-proxy --from :80 --to 127.0.0.1:80
# Mount Compass Web at the root path
$ stack mount \
--require 127.0.0.1:27017 \
--env 'CW_MONGO_URI=mongodb://1.localhost:27017,2.localhost:27017,3.localhost:27017/?replicaSet=rs0' \
haohanyang/compass-web \
mongo.rs.microstacks.com/
# Import MongoDB with replica set mode enabled
$ stack import \
mongo:8.3.7 \
mongo.rs.microstacks.com/mongo -- \
mongod --replSet rs0 --bind_ip '${INSTANCE}.localhost'
# Clone the MongoDB service block under itself
$ stack import \
mongo.rs.microstacks.com/mongo \
mongo.rs.microstacks.com/mongo/mongo
# Run a config job to initialize the replica set
$ stack import \
--no-restart \
--require 127.0.0.{1..3}:27017 \
alpine/mongosh:latest \
mongo.rs.microstacks.com/config -- \
mongosh --host 1.localhost --eval 'rs.initiate({_id:"rs0",members:[{_id:0,host:"1.localhost:27017"}]}); while (!db.hello().isWritablePrimary) { sleep(1000); }; rs.add("2.localhost:27017"); rs.add("3.localhost:27017"); rs.status()'
# Link MongoDB into the config address space
$ stack import \
mongo.rs.microstacks.com/mongo \
mongo.rs.microstacks.com/config/mongo
# Snap Compass Web and the MongoDB replica vectors
$ stack snap -r mongo.rs.microstacks.com
$ stack snap mongo.rs.microstacks.com/mongo
$ stack snap mongo.rs.microstacks.com/mongo
A sharded MongoDB cluster mapped to mongo.cluster.microstacks.com. Map Caddy as the router, mount Compass Web, define query, config, and shard blocks, wire their address spaces, and snap the cluster vectors.
# Map Caddy as the router for the MongoDB cluster domain
$ stack map caddy:2 mongo.cluster.microstacks.com -- \
caddy reverse-proxy --from :80 --to 127.0.0.1:80
# Mount Compass Web at the root path
$ stack mount \
--require 127.0.0.1:27017 \
--env 'CW_MONGO_URI=mongodb://127.0.0.1:27017' \
--http-port 8080 \
haohanyang/compass-web \
mongo.cluster.microstacks.com/ -- \
compass-web --host 0.0.0.0
# Import the mongos query router
$ stack import \
--require 127.0.0.{1..3}:27019 \
mongo:8.3.7 \
mongo.cluster.microstacks.com/query -- \
mongos --configdb cfg/127.0.0.1:27019,127.0.0.2:27019,127.0.0.3:27019 --bind_ip '${INSTANCE}.microstacks'
# Import the config server replica set
$ stack import \
--mask 27017/tcp \
--endpoint 27019/tcp \
mongo:8.3.7 \
mongo.cluster.microstacks.com/query/config -- \
mongod --configsvr --replSet cfg --bind_ip '${INSTANCE}.microstacks'
# Import shard0
$ stack import \
--mask 27017/tcp \
--endpoint 27018/tcp \
mongo:8.3.7 \
mongo.cluster.microstacks.com/query/shard0 -- \
mongod --shardsvr --replSet shard0 --bind_ip '${INSTANCE}.microstacks'
# Import shard1
$ stack import \
--mask 27017/tcp \
--endpoint 27028/tcp \
mongo:8.3.7 \
mongo.cluster.microstacks.com/query/shard1 -- \
mongod --shardsvr --replSet shard1 --bind_ip '${INSTANCE}.microstacks' --port 27028
# Initialize config and shard replica sets
$ stack import \
--no-restart \
--require 127.0.0.{1..3}:27019 \
--require 127.0.0.{1..2}:27018 \
--require 127.0.0.{1..2}:27028 \
alpine/mongosh:latest \
mongo.cluster.microstacks.com/init -- \
mongosh --nodb --quiet --eval \
'new Mongo("127.0.0.1:27019").getDB("admin").runCommand({replSetInitiate:{_id:"cfg",configsvr:true,members:[{_id:0,host:"127.0.0.1:27019"},{_id:1,host:"127.0.0.2:27019"},{_id:2,host:"127.0.0.3:27019"}]}});
new Mongo("127.0.0.1:27018").getDB("admin").runCommand({replSetInitiate:{_id:"shard0",members:[{_id:0,host:"127.0.0.1:27018"},{_id:1,host:"127.0.0.2:27018"}]}});
new Mongo("127.0.0.1:27028").getDB("admin").runCommand({replSetInitiate:{_id:"shard1",members:[{_id:0,host:"127.0.0.1:27028"},{_id:1,host:"127.0.0.2:27028"}]}});'
# Add shards through the query router
$ stack import \
--no-restart \
--require 127.0.0.1:27017 \
--require 127.0.0.{1..2}:27018 \
--require 127.0.0.{1..2}:27028 \
alpine/mongosh:latest \
mongo.cluster.microstacks.com/config -- \
mongosh --host 127.0.0.1:27017 --quiet --eval \
'db.adminCommand({addShard:"shard0/127.0.0.1:27018,127.0.0.2:27018"});
db.adminCommand({addShard:"shard1/127.0.0.1:27028,127.0.0.2:27028"});
sh.status();'
# Link query, config, shard, init, and config job address spaces
$ stack import mongo.cluster.microstacks.com/query \
mongo.cluster.microstacks.com/query/query \
mongo.cluster.microstacks.com/config/
$ stack import mongo.cluster.microstacks.com/query/config \
mongo.cluster.microstacks.com/query/config/config \
mongo.cluster.microstacks.com/{query/shard0,query/shard1,init}/
$ stack import mongo.cluster.microstacks.com/query/shard0 \
mongo.cluster.microstacks.com/{init,config,query/config}/ \
mongo.cluster.microstacks.com/query/shard0/shard0
$ stack import mongo.cluster.microstacks.com/query/shard1 \
mongo.cluster.microstacks.com/{init,config,query/config}/ \
mongo.cluster.microstacks.com/query/shard1/shard1
# Snap the MongoDB cluster vectors
$ stack snap -r mongo.cluster.microstacks.com
$ stack snap mongo.cluster.microstacks.com/query/config{,}
$ stack snap mongo.cluster.microstacks.com/query/shard{0,1}
The same model is available from code. You can define blocks, mount paths, import services, and snap vectors programmatically, then version and test those changes like the rest of your application.
package main import ( "github.com/microstacks/stack" "github.com/microstacks/stack/block" "github.com/microstacks/stack/vector" ) func main() { hub, _ := stack.Hub("https://example.com") gw, _ := hub.Gateway("example.com") root, _ := gw.Root() // Define a block — same fields as `stack import`. api := block.New("myorg/api:1.4", block.Kind(block.SERVICE), block.Env("DB_URL", "postgres://db/app"), block.Endpoint(8080, "tcp"), ) // Mount at /api (like `stack mount`). root.Mount(api, "/api") // Place vectors close to users in two regions. api.Snap(vector.Node{Address: "ssh://ops@edge-fra1"}) api.Snap(vector.Node{Address: "ssh://ops@edge-sin1"}) }
self hosted
Run a single-node block stack and vector map together on infrastructure you manage.
DownloadDeploy
$99/mo
Join waitlistSingle-node vector map
A managed single-node block stack connected to one vector map node in the cloud environment you choose.
Included features
Snap
$299/mo
Join waitlistSingle-cloud vector scaling
A three-node HA quorum block stack supporting a multi-node vector map inside one cloud environment.
Everything in Deploy, plus
Scale
$499/mo
Join waitlistFederated multi-cloud vector map
A five-node fault-tolerant quorum block stack supporting vector maps distributed across multiple clouds.
Everything in Snap, plus