diff --git a/cmd/bor/chaincmd.go b/cmd/bor/chaincmd.go
index 9747ac0ecf261fc7c7cbb6149dbaf2ec1e21b893..78bbc56df9b9c56b354d3491fa96bb2569ca8765 100644
--- a/cmd/bor/chaincmd.go
+++ b/cmd/bor/chaincmd.go
@@ -78,6 +78,7 @@ The dumpgenesis command dumps the genesis block configuration in JSON format to
 		Flags: []cli.Flag{
 			utils.DataDirFlag,
 			utils.HeimdallURLFlag,
+			utils.WithoutHeimdallFlag,
 			utils.CacheFlag,
 			utils.SyncModeFlag,
 			utils.GCModeFlag,
diff --git a/cmd/bor/config.go b/cmd/bor/config.go
index 7bedfcdd24a12c9fbb354fbe71264c35d779a956..a59664e92a5e780049c2d5a12d862e7331c59920 100644
--- a/cmd/bor/config.go
+++ b/cmd/bor/config.go
@@ -148,7 +148,12 @@ func enableWhisper(ctx *cli.Context) bool {
 func makeFullNode(ctx *cli.Context) *node.Node {
 	stack, cfg := makeConfigNode(ctx)
 	cfg.Eth.HeimdallURL = ctx.GlobalString(utils.HeimdallURLFlag.Name)
-	log.Info("Connecting to heimdall service on...", "heimdallURL", cfg.Eth.HeimdallURL)
+	cfg.Eth.WithoutHeimdall = ctx.GlobalBool(utils.WithoutHeimdallFlag.Name)
+	if cfg.Eth.WithoutHeimdall {
+		log.Info("Running without Heimdall node")
+	} else {
+		log.Info("Connecting to Heimdall node", "heimdallURL", cfg.Eth.HeimdallURL)
+	}
 	utils.RegisterEthService(stack, &cfg.Eth)
 
 	// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
diff --git a/cmd/bor/main.go b/cmd/bor/main.go
index 4d914942996871502ff96c03bc51e2d67c321b95..e1eb386ac62efca2e0a982c06331446fdc41bcdd 100644
--- a/cmd/bor/main.go
+++ b/cmd/bor/main.go
@@ -211,6 +211,7 @@ var (
 
 	borFlags = []cli.Flag{
 		utils.HeimdallURLFlag,
+		utils.WithoutHeimdallFlag,
 	}
 )
 
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index d0b39a7734dee590591d680abf9fa15d3772d527..75cdc5131a884e794c1d102c46ea2bc6fc5bd1d5 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -751,12 +751,22 @@ var (
 		Value: "",
 	}
 
+	//
 	// Bor Specific flags
+	//
+
+	// HeimdallURLFlag flag for heimdall url
 	HeimdallURLFlag = cli.StringFlag{
 		Name:  "heimdall",
 		Usage: "URL of Heimdall service",
 		Value: "http://localhost:1317",
 	}
+
+	// WithoutHeimdallFlag no heimdall (for testing purpose)
+	WithoutHeimdallFlag = cli.BoolFlag{
+		Name:  "without-heimdall",
+		Usage: "Run without Heimdall service (for testing purpose)",
+	}
 )
 
 // MakeDataDir retrieves the currently requested data directory, terminating
@@ -1872,7 +1882,11 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readOnly bool) (chain *core.B
 	if config.Clique != nil {
 		engine = clique.New(config.Clique, chainDb)
 	} else if config.Bor != nil {
-		cfg := &eth.Config{Genesis: genesis, HeimdallURL: ctx.GlobalString(HeimdallURLFlag.Name)}
+		cfg := &eth.Config{
+			Genesis:         genesis,
+			HeimdallURL:     ctx.GlobalString(HeimdallURLFlag.Name),
+			WithoutHeimdall: ctx.GlobalBool(WithoutHeimdallFlag.Name),
+		}
 		workspace, err := ioutil.TempDir("", "console-tester-")
 		if err != nil {
 			Fatalf("failed to create temporary keystore: %v", err)
diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go
index ee0a66cad016d09a5267c7af66eff73bec518267..ae693906d3fa4722163cc290f69e23e57b4d67f1 100644
--- a/consensus/bor/bor.go
+++ b/consensus/bor/bor.go
@@ -224,6 +224,7 @@ type Bor struct {
 	validatorSetABI        abi.ABI
 	stateReceiverABI       abi.ABI
 	HeimdallClient         IHeimdallClient
+	WithoutHeimdall        bool
 
 	stateSyncFeed event.Feed
 	scope         event.SubscriptionScope
@@ -237,6 +238,7 @@ func New(
 	db ethdb.Database,
 	ethAPI *ethapi.PublicBlockChainAPI,
 	heimdallURL string,
+	withoutHeimdall bool,
 ) *Bor {
 	// get bor config
 	borConfig := chainConfig.Bor
@@ -264,6 +266,7 @@ func New(
 		stateReceiverABI:       sABI,
 		GenesisContractsClient: genesisContractsClient,
 		HeimdallClient:         heimdallClient,
+		WithoutHeimdall:        withoutHeimdall,
 	}
 
 	return c
@@ -653,7 +656,7 @@ func (c *Bor) Prepare(chain consensus.ChainReader, header *types.Header) error {
 // rewards given.
 func (c *Bor) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) {
 	headerNumber := header.Number.Uint64()
-	if headerNumber%c.config.Sprint == 0 {
+	if !c.WithoutHeimdall && headerNumber%c.config.Sprint == 0 {
 		cx := chainContext{Chain: chain, Bor: c}
 		// check and commit span
 		if err := c.checkAndCommitSpan(state, header, cx); err != nil {
@@ -677,7 +680,7 @@ func (c *Bor) Finalize(chain consensus.ChainReader, header *types.Header, state
 // nor block rewards given, and returns the final block.
 func (c *Bor) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
 	headerNumber := header.Number.Uint64()
-	if headerNumber%c.config.Sprint == 0 {
+	if !c.WithoutHeimdall && headerNumber%c.config.Sprint == 0 {
 		cx := chainContext{Chain: chain, Bor: c}
 
 		// check and commit span
diff --git a/eth/backend.go b/eth/backend.go
index 3ae11fa0aa6b83e8dca996ab45732a78f74c0b3c..efffc64da1408588e51b018bfdbe90e08eea1096 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -273,7 +273,7 @@ func CreateConsensusEngine(ctx *node.ServiceContext, chainConfig *params.ChainCo
 
 	// If Matic Bor is requested, set it up
 	if chainConfig.Bor != nil {
-		return bor.New(chainConfig, db, ee, ethConfig.HeimdallURL)
+		return bor.New(chainConfig, db, ee, ethConfig.HeimdallURL, ethConfig.WithoutHeimdall)
 	}
 
 	// Otherwise assume proof-of-work
diff --git a/eth/config.go b/eth/config.go
index ba8f73735bdd8588b6856f7669c2162bfab19437..46ebcf83180b0a918ced49aaae39cbfd9bacf9a4 100644
--- a/eth/config.go
+++ b/eth/config.go
@@ -182,4 +182,7 @@ type Config struct {
 
 	// URL to connect to Heimdall node
 	HeimdallURL string
+
+	// No heimdall service
+	WithoutHeimdall bool
 }