Run a service locally

Running a service locally is helpful to test and debug. The following sections provide commands for starting and stopping a single service locally.


In order to run your service locally, you’ll need to have the following prerequisites:

  • Docker 20.10.14 or higher

  • Access to the container registry

  • Your service packaged as a container

The samples provided with the Kalix SDKs all have docker-compose files preconfigured to run your service locally. They also contain the configuration to start a local Google Pub/Sub emulator that the Kalix proxy will connect to when you make use of topic-based Eventing in your service.

Starting your service

To start the proxy, run the following command from the directory with the docker-compose.yml file:

  1. Start the proxy

    docker compose up
  2. Start the service

    mvn compile exec:exec
    npm start
    sbt run

By default this command will start your containers in foreground mode. This means the terminal window will show all output from all containers. To start in "detached" mode, add the -d or --detach flag to the docker compose commands.

Invoking your service

After you start the service it will accept invocations on localhost:9000. You can use gRPCurl or cURL to invoke your service.

Using cURL

Linux or macOS
curl \
  -XPOST \ (1)
  -H "Content-Type: application/json" \ (2)
  -d '{"counterId": "foo"}' \ (3)
  localhost:9000/com.example.CounterService/GetCurrentCounter (4)
Windows 10+
curl ^
  -XPOST ^ (1)
  -H "Content-Type: application/json" ^ (2)
  -d '{"counterId": "foo"}' ^ (3)
  localhost:9000/com.example.CounterService/GetCurrentCounter (4)
1 The XPOST flag indicates cURL will send a POST request
2 The content type for this request is set to application/json
3 The message payload in JSON format
4 The URL with the RPC procedure name which is deduced from the protobuf definition of the component you’re calling.

Using gRPCurl

Inspect your services with the gRPC list and describe commands:

grpcurl -plaintext localhost:9000 list

grpcurl -plaintext localhost:9000 describe com.example.CounterService

Get a current value from the CounterService:

Linux or macOS
grpcurl \
  -d '{"counterId": "foo"}' \ (1)
  -plaintext localhost:9000 \ (2)
  com.example.CounterService/GetCurrentCounter (3)
Windows 10+
grpcurl ^
  -d '{"counterId": "foo"}' ^ (1)
  -plaintext localhost:9000 ^ (2)
  com.example.CounterService/GetCurrentCounter (3)
1 The message payload in JSON format with -d
2 The address of the proxy (using plaintext instead of TLS)
3 The RPC procedure name which is deduced from the protobuf definition of the component you’re calling.

Shut down the proxy

To shut down the proxy, which removes all data kept in memory, run the command below:

docker stop kalix-proxy

To delete the proxy container, run

docker rm kalix-proxy

Running multiple services

You can run multiple services at the same time. To do that, each service will need its own proxy container. Each proxy container will need its own port.

To update the docker compose file to run multiple proxy instances, add the snippet below:

kalix-proxy: (1)
  command: -Dconfig.resource=dev-mode.conf
    - "900x:9000" (2)
    USER_FUNCTION_HOST: ${USER_FUNCTION_HOST:-host.docker.internal}
1 This name has to be unique in your docker compose file (docker compose uses this name to uniquely identify the running container)
2 The host port ("900x") in the port mapping must be unique for each proxy instance
3 The user function port must be unique for each service you start. You can set the port on which your service listens in the start method.