Flow Local Instrumented Test Environment (FLITE)
August 13, 2026 · View on GitHub
FLITE is a tool for running a full version of the Flow blockchain.
Table of Contents
- Prerequisites
- Bootstrapping
- Start the network
- Stop the network
- Build Localnet images
- Verify the network is working
- Logs
- Observability
- Benchmarking
- Debugging
- Playing with Localnet
- admin tool
Prerequisites
Required:
- Docker with the Compose plugin (
docker compose) - Go - bootstrapping runs the network builder with
go run
Optional:
- Flow CLI - for the examples in Playing with Localnet
- grpcurl - for querying the access node gRPC API directly
Bootstrapping
Before running the Flow network it is necessary to run a bootstrapping process. This generates keys for each of the nodes and a genesis block to build on.
Bootstrap a new network (from integration/localnet directory):
make bootstrap
Configuration
Various properties of the local network can be configured when it is initialized. All configuration is optional.
Specify the number of nodes for each role:
make -e COLLECTION=2 CONSENSUS=5 EXECUTION=3 VERIFICATION=2 ACCESS=2 bootstrap
NOTE: number of execution\consensus nodes should be no less than 2. It is to avoid seals being created in case of execution forks.
Specify the number of collector clusters:
make -e NCLUSTERS=3 bootstrap
Profiling
You can turn on automatic profiling for all nodes. Profiles are written every 2
minutes to ./profiler.
make -e PROFILER=true bootstrap
Start the network
This command will automatically build new Docker images from your latest code changes and then start the test network:
make start
Alternatively, this command will start the test network without re-building, using the most recently built image.
make start-cached
Stop the network
make stop
Chain state persists across restarts - it is stored in the ./data directory, which is
bind-mounted into the node containers. To start from a fresh genesis, stop the network,
remove the generated data, and re-bootstrap:
make stop
make clean-data
make bootstrap
Build Localnet images
To build images for Localnet, run this command.
make build-flow
Verify the network is working
Once the network is running, you can smoke-test that it is producing and sealing blocks:
make verify
This polls the access node REST API (http://localhost:4004) and confirms the sealed block height is increasing.
Logs
You can view log output from all nodes:
make logs
Observability
You can view realtime metrics, logs, and traces while the network is running:
- Grafana: http://localhost:3000/
Metrics
Metrics are available through the Prometheus backend.
Following dashboards are preinstalled:
Here's an example of a Prometheus query that filters by the consensus role:
avg(rate(consensus_compliance_finalized_blocks_total{role="consensus"}[$__interval]))
Traces
Traces are available through the Tempo backend.
You can get to traces either by searching for logs that have a traceID label, clicking on them and pressing "Open in Tempo" button:
{role="execution"} | json | __error__ != "JSONParserErr" | timeSpentInMS > 10 | traceID != ""
Or by using the grafana's Search feature in explore:
Logs
Logs are available through the Loki backend. You can use them either through the Logs/TimeSeries panels or through the explore:
Benchmarking
To load a running localnet with transactions, use the TPS loader from the flow-execution-effort-estimation repository (private - requires repository access).
The localnet is already set up for it: the docker network is attachable, the loader's
Prometheus scrape target (loader:8443) is pre-configured, and a loader dashboard is
installed in the local Grafana. From the root of the loader repository, run:
make load-local
Load progress can be observed in the local Grafana (http://localhost:3000) via the
flow_execution_effort_estimation_* metrics.
More about the loader can be found in the loader repository.
Debugging
It is possible to connect a debugger to a localnet instance to debug the code. To set this up, find the
node you want to debug in docker-compose.nodes.yml, then make the following changes to its config:
- Set the build
targetsetting todebug. This configures it to use the specialdebugimage which runs the node application withindlv.build: ... target: debug - Expose the debugger ports to your host network
ports: ... - "2345:2345" - Rebuild the node. In these examples, we are rebuilding the
execution_1node.docker compose -f docker-compose.nodes.yml build execution_1 - Stop and restart the node
docker compose -f docker-compose.nodes.yml stop execution_1 docker compose -f docker-compose.nodes.yml up -d execution_1 - Check the logs to make sure it's working
docker compose -f docker-compose.nodes.yml logs -f execution_1 localnet-execution_1-1 | API server listening at: [::]:2345 - Configure your debugger client to connect. Here is a vscode launch config as an example:
{ "name": "Connect to container", "type": "go", "request": "attach", "mode": "remote", "debugAdapter": "dlv-dap", "substitutePath": [ { "from": "${workspaceFolder}", "to": "/app", }, ], "port": 2345, "trace": "verbose" },
Notes:
JSON-rpconly supports connecting to the headless server once. You will need to restart the node to connect again.Debug Adaptor Protocol (DAP)supports reconnecting.- The Dockerfile is configured to pause the application until the debugger connects. This ensures
JSON-rpcclients can connect. If you are connecting withDAPand would like the node to start immediately, update the debugENTRYPOINTin the Dockerfile to include--continue=true.
Playing with Localnet
This section documents how can be localnet used for experimenting with the network.
Configure Flow CLI to work with localnet
Follow documentation to install and initialize the Flow CLI.
Add localnet network
Modify Flow CLI configuration file and add "localnet" network, using access node address/port with values displayed by the localnet initialization step.
An example of the Flow CLI configuration modified for connecting to the localnet:
{
"networks": {
"localnet": "127.0.0.1:4001"
}
}
You can test the connection to the localnet by for example querying service account address:
flow -n localnet accounts get f8d6e0586b0a20c7
Add service account address and private key
The service account private key is hardcoded for localnet and can be found in unit test utility execution state.
The service account address is derived from network ID (in this case "flow-localnet") and the generated service account address is "f8d6e0586b0a20c7".
Note: you can also get the address via
Chain interface ServiceAddress()method.
Create new entry in the Flow CLI config "accounts" section for the localnet service account and add the service account address and private key using the advanced format.
An example of the Flow CLI configuration with the service account added:
{
"networks": {
"localnet": "127.0.0.1:4001"
},
"accounts": {
"localnet-service-account": {
"address": "f8d6e0586b0a20c7",
"key":{
"type": "hex",
"index": 0,
"signatureAlgorithm": "ECDSA_P256",
"hashAlgorithm": "SHA2_256",
"privateKey": "8ae3d0461cfed6d6f49bfc25fa899351c39d1bd21fdba8c87595b6c49bb4cc43"
}
}
}
}
Note: recent Flow CLI versions print a security warning about private keys stored directly in
flow.json. This is expected here - the localnet service account key is publicly known and holds no value.
to check if the address above really is a service account, query the service account address:
flow -n localnet accounts get f8d6e0586b0a20c7
and check that the output contains Contract: 'FlowServiceAccount'.
Configure contract addresses for localnet
When you send transaction via CLI, the cadence contract you provide to the CLI will likely need to reference other contracts deployed on the network. You can configure the CLI to substitute the contract addresses on different networks. For example, to run this contract, you will need to import FungibleToken and FlowToken.
Add this block to your Flow CLI configuration file "contracts" section:
"FungibleToken": {
"source": "cadence/contracts/FungibleToken.cdc",
"aliases": {
"localnet": "0xee82856bf20e2aa6",
"emulator": "0xee82856bf20e2aa6",
"testnet": "0x9a0766d93b6608b7"
}
},
"FlowToken": {
"source": "cadence/contracts/FlowToken.cdc",
"aliases": {
"localnet": "0x0ae53cb6e3f42a79",
"emulator": "0x0ae53cb6e3f42a79",
"testnet": "0x7e60df042a9c0868"
}
}
Note: The actual address values can also be found in Flow Documentation for Fungible Token Contract and Flow Token Contract.
Using Flow CLI to send transaction to localnet
Creating new account on the localnet
Create keys for a new account:
flow keys generate -n localnet
Use the generated public key in the following command:
flow accounts create --key <GENERATED_PUBLIC_KEY> --signer localnet-service-account -n localnet
After the transaction is sealed the command should print the account address and balance.
Getting account information
To verify that the account created in the previous section exists, or to check the balance etc. you can run:
flow -n localnet accounts get <ACCOUNT_ADDRESS>
Running a cadence script
This script below reads the balance field of an account's FlowToken Balance.
Create a file (for example my_script.cdc) containing following cadence code:
import FungibleToken from 0xee82856bf20e2aa6
import FlowToken from 0x0ae53cb6e3f42a79
access(all)
fun main(address: Address): UFix64 {
let acct = getAccount(address)
let vaultRef = acct.capabilities.borrow<&FlowToken.Vault{FungibleToken.Balance}>(/public/flowTokenBalance)
?? panic("Could not borrow Balance reference to the Vault")
return vaultRef.balance
}
Run the script:
flow scripts execute -n localnet ~/my_script.cdc "<ACCOUNT_ADDRESS>"
replace
<ACCOUNT_ADDRESS>in the command above with an address that you created on your localnet.
The script should output the account balance of the specified account.
You can also execute simple script without creating files, by providing the script in the command, for example:
# flow scripts execute -n localnet <(echo """
access(all)
fun main(address: Address): UFix64 {
return getAccount(address).balance
}
""") "<ACCOUNT_ADDRESS>"
Moving tokens from the service account to another account
Create new cadence contract file from this template. Make sure that contract imports have values that match your cli config, following the CLI configuration chapter above it should look like:
import "FungibleToken"
import "FlowToken"
Send the transaction with this contract to localnet:
flow transactions send transfer_tokens.cdc 9999.9 <ACCOUNT_ADDRESS> -n localnet --signer localnet-service-account
replace
<ACCOUNT_ADDRESS>in the command above with an address that you created on your localnet.
After the transaction is sealed, the account with <ACCOUNT_ADDRESS> should have the balance increased by 9999.9 tokens.
admin tool
The admin tool is enabled by default in localnet for all node types.
For instance, in order to use admin tool to change log level, first find the local port that maps to 9002 which is the admin tool address, if the local port is 6100, then run:
curl localhost:6100/admin/run_command -H 'Content-Type: application/json' -d '{"commandName": "set-log-level", "data": "debug"}'
To find the local port after launching the localnet, run docker ps -a, and find the port mapping.
For instance, the following result of docker ps -a shows localnet-collection maps 9002 port to localhost's 6100 port, so we could use 6100 port to connect to admin tool.
2e0621f7e592 localnet-access "/bin/app --nodeid=9…" 9 seconds ago Up 8 seconds 0.0.0.0:4011->9000/tcp, :::4011->9000/tcp, 0.0.0.0:4012->9001/tcp, :::4012->9001/tcp localnet_access_2_1
fcd92116f902 localnet-collection "/bin/app --nodeid=0…" 9 seconds ago Up 8 seconds 0.0.0.0:6100->9002/tcp, :::6100->9002/tcp localnet_collection_1_1
dd841d389e36 localnet-access "/bin/app --nodeid=a…" 10 seconds ago Up 9 seconds 0.0.0.0:4001->9000/tcp, :::4001->9000/tcp, 0.0.0.0:4002->9001/tcp, :::4002->9001/tcp localnet_access_1_1