Repository: nats-io/nats-server
Pull request #3326 (2022-08-03 08:33:20)

Added param options to /healthz endpoint
 - [x] Link to issue, e.g. `Resolves #NNN`
 - [x] Documentation added (if applicable)
 - [x] Tests added
 - [x] Branch rebased on top of current main (`git pull --rebase origin main`)
 - [x] Changes squashed to a single commit (described [here](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html))
 - [x] Build is green in Travis CI
 - [x] You have certified that the contribution is your original work and that you license the work to the project under the [Apache 2 license](https://github.com/nats-io/nats-server/blob/main/LICENSE)

Related to # https://github.com/nats-io/k8s/issues/541
Resolves # The JetStream portion of https://github.com/nats-io/nats-server/issues/2687

### Changes proposed in this pull request:

 - Added `/healthz?js-enabled=true` to return error if JetStream is disabled.
 - Added `/healthz?js-server-only=true` to skip checking of JetStream accounts, streams and consumers.

/cc @nats-io/core


mfaizanse: /retest

Patch:
diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml
index 631255aa..d19efbbe 100644
--- a/.github/workflows/nightly.yaml
+++ b/.github/workflows/nightly.yaml
@@ -23,7 +23,7 @@ jobs:
       - name: Set up Go
         uses: actions/setup-go@v2
         with:
-          go-version: 1.19
+          go-version: 1.18
 
       - name: goreleaser
         uses: goreleaser/goreleaser-action@v2
diff --git a/.gitignore b/.gitignore
index dd7aaf4f..d4dc84d9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,7 +6,6 @@
 # Folders
 _obj
 _test
-dist
 
 # Configuration Files
 *.conf
@@ -37,9 +36,6 @@ _testmain.go
 \#*\#
 .\#*
 
-# Visual Studio Code
-.vscode
-
 # Mac
 .DS_Store
 
diff --git a/.travis.yml b/.travis.yml
index 683221fb..26d8c508 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,7 +7,7 @@ vm:
 
 language: go
 go:
-- 1.19.x
+- 1.18.x
 
 addons:
   apt:
@@ -32,7 +32,7 @@ jobs:
     - name: "Run all tests from all other packages"
       env: TEST_SUITE=non_srv_pkg_tests
     - name: "Compile with older Go release"
-      go: 1.18.x
+      go: 1.17.x
       env: TEST_SUITE=build_only
 
 script: ./scripts/runTestsOnTravis.sh $TEST_SUITE
@@ -43,4 +43,4 @@ deploy:
   script: curl -sL http://git.io/goreleaser | bash
   on:
     tags: true
-    condition: ($TRAVIS_GO_VERSION =~ 1.19) && ($TEST_SUITE = "compile")
+    condition: ($TRAVIS_GO_VERSION =~ 1.18) && ($TEST_SUITE = "compile")
diff --git a/conf/parse.go b/conf/parse.go
index d1e29819..afb6f6e8 100644
--- a/conf/parse.go
+++ b/conf/parse.go
@@ -27,6 +27,7 @@ package conf
 
 import (
 	"fmt"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strconv"
@@ -71,7 +72,7 @@ func Parse(data string) (map[string]interface{}, error) {
 
 // ParseFile is a helper to open file, etc. and parse the contents.
 func ParseFile(fp string) (map[string]interface{}, error) {
-	data, err := os.ReadFile(fp)
+	data, err := ioutil.ReadFile(fp)
 	if err != nil {
 		return nil, fmt.Errorf("error opening config file: %v", err)
 	}
@@ -85,7 +86,7 @@ func ParseFile(fp string) (map[string]interface{}, error) {
 
 // ParseFileWithChecks is equivalent to ParseFile but runs in pedantic mode.
 func ParseFileWithChecks(fp string) (map[string]interface{}, error) {
-	data, err := os.ReadFile(fp)
+	data, err := ioutil.ReadFile(fp)
 	if err != nil {
 		return nil, err
 	}
diff --git a/docker/Dockerfile.nightly b/docker/Dockerfile.nightly
index 13fa7d54..ba08ba8f 100644
--- a/docker/Dockerfile.nightly
+++ b/docker/Dockerfile.nightly
@@ -1,4 +1,4 @@
-FROM golang:1.19-alpine AS builder
+FROM golang:1.18-alpine AS builder
 
 ARG VERSION="nightly"
 
diff --git a/go.mod b/go.mod
index 64f00f91..53acdb65 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ require (
 	github.com/klauspost/compress v1.15.9
 	github.com/minio/highwayhash v1.0.2
 	github.com/nats-io/jwt/v2 v2.3.0
-	github.com/nats-io/nats.go v1.16.1-0.20220803221958-cc189da40f83
+	github.com/nats-io/nats.go v1.16.0
 	github.com/nats-io/nkeys v0.3.0
 	github.com/nats-io/nuid v1.0.1
 	go.uber.org/automaxprocs v1.5.1
diff --git a/go.sum b/go.sum
index 605612f3..45bd2654 100644
--- a/go.sum
+++ b/go.sum
@@ -15,8 +15,8 @@ github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA
 github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
 github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI=
 github.com/nats-io/jwt/v2 v2.3.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k=
-github.com/nats-io/nats.go v1.16.1-0.20220803221958-cc189da40f83 h1:EAK6rdyLzKzw3Cklsth//yfG2rZn0jdvCVuUdpFbpzQ=
-github.com/nats-io/nats.go v1.16.1-0.20220803221958-cc189da40f83/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
+github.com/nats-io/nats.go v1.16.0 h1:zvLE7fGBQYW6MWaFaRdsgm9qT39PJDQoju+DS8KsO1g=
+github.com/nats-io/nats.go v1.16.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
 github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
 github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
 github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
diff --git a/server/accounts.go b/server/accounts.go
index a7081f25..e9a814f8 100644
--- a/server/accounts.go
+++ b/server/accounts.go
@@ -20,7 +20,7 @@ import (
 	"fmt"
 	"hash/fnv"
 	"hash/maphash"
-	"io"
+	"io/ioutil"
 	"math"
 	"math/rand"
 	"net/http"
@@ -1326,10 +1326,7 @@ func (a *Account) sendBackendErrorTrackingLatency(si *serviceImport, reason rsiR
 // received the response.
 // TODO(dlc) - holding locks for RTTs may be too much long term. Should revisit.
 func (a *Account) sendTrackingLatency(si *serviceImport, responder *client) bool {
-	a.mu.RLock()
-	rc := si.rc
-	a.mu.RUnlock()
-	if rc == nil {
+	if si.rc == nil {
 		return true
 	}
 
@@ -3601,7 +3598,7 @@ func (ur *URLAccResolver) Fetch(name string) (string, error) {
 		return _EMPTY_, fmt.Errorf("could not fetch <%q>: %v", redactURLString(url), resp.Status)
 	}
 	defer resp.Body.Close()
-	body, err := io.ReadAll(resp.Body)
+	body, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		return _EMPTY_, err
 	}
diff --git a/server/const.go b/server/const.go
index 0a8a1b76..a82ccce2 100644
--- a/server/const.go
+++ b/server/const.go
@@ -41,7 +41,7 @@ var (
 
 const (
 	// VERSION is the current version for the server.
-	VERSION = "2.9.0-beta.22"
+	VERSION = "2.9.0-beta.17"
 
 	// PROTO is the currently supported protocol.
 	// 0 was the original
diff --git a/server/dirstore.go b/server/dirstore.go
index cabd4a19..9bb499fd 100644
--- a/server/dirstore.go
+++ b/server/dirstore.go
@@ -20,6 +20,7 @@ import (
 	"crypto/sha256"
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"math"
 	"os"
 	"path/filepath"
@@ -145,8 +146,8 @@ const (
 //
 // limit defines how many files are allowed at any given time. Set to math.MaxInt64 to disable.
 // evictOnLimit determines the behavior once limit is reached.
-// * true - Evict based on lru strategy
-// * false - return an error
+//     true - Evict based on lru strategy
+//     false - return an error
 func NewExpiringDirJWTStore(dirPath string, shard bool, create bool, delete deleteType, expireCheck time.Duration, limit int64,
 	evictOnLimit bool, ttl time.Duration, changeNotification JWTChanged, _ ...dirJWTStoreOption) (*DirJWTStore, error) {
 	fullPath, err := newDir(dirPath, create)
@@ -174,7 +175,7 @@ func NewExpiringDirJWTStore(dirPath string, shard bool, create bool, delete dele
 	theStore.Lock()
 	err = filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
 		if strings.HasSuffix(path, fileExtension) {
-			if theJwt, err := os.ReadFile(path); err == nil {
+			if theJwt, err := ioutil.ReadFile(path); err == nil {
 				hash := sha256.Sum256(theJwt)
 				_, file := filepath.Split(path)
 				theStore.expiration.track(strings.TrimSuffix(file, fileExtension), &hash, string(theJwt))
@@ -240,7 +241,7 @@ func (store *DirJWTStore) Pack(maxJWTs int) (string, error) {
 					return nil // only include indexed files
 				}
 			}
-			jwtBytes, err := os.ReadFile(path)
+			jwtBytes, err := ioutil.ReadFile(path)
 			if err != nil {
 				return err
 			}
@@ -284,7 +285,7 @@ func (store *DirJWTStore) PackWalk(maxJWTs int, cb func(partialPackMsg string))
 				}
 			}
 			store.Unlock()
-			jwtBytes, err := os.ReadFile(path)
+			jwtBytes, err := ioutil.ReadFile(path)
 			if err != nil {
 				return err
 			}
@@ -350,7 +351,7 @@ func (store *DirJWTStore) Reload() error {
 	store.Unlock()
 	return filepath.Walk(store.directory, func(path string, info os.FileInfo, err error) error {
 		if strings.HasSuffix(path, fileExtension) {
-			if theJwt, err := os.ReadFile(path); err == nil {
+			if theJwt, err := ioutil.ReadFile(path); err == nil {
 				hash := sha256.Sum256(theJwt)
 				_, file := filepath.Split(path)
 				pkey := strings.TrimSuffix(file, fileExtension)
@@ -393,7 +394,7 @@ func (store *DirJWTStore) load(publicKey string) (string, error) {
 	defer store.Unlock()
 	if path := store.pathForKey(publicKey); path == _EMPTY_ {
 		return _EMPTY_, fmt.Errorf("invalid public key")
-	} else if data, err := os.ReadFile(path); err != nil {
+	} else if data, err := ioutil.ReadFile(path); err != nil {
 		return _EMPTY_, err
 	} else {
 		if store.expiration != nil {
@@ -431,7 +432,7 @@ func (store *DirJWTStore) write(path string, publicKey string, theJWT string) (b
 			}
 		}
 	}
-	if err := os.WriteFile(path, []byte(theJWT), defaultFilePerms); err != nil {
+	if err := ioutil.WriteFile(path, []byte(theJWT), defaultFilePerms); err != nil {
 		return false, err
 	} else if store.expiration != nil {
 		store.expiration.track(publicKey, newHash, theJWT)
@@ -513,7 +514,7 @@ func (store *DirJWTStore) saveIfNewer(publicKey string, theJWT string) error {
 	if _, err := os.Stat(path); err == nil {
 		if newJWT, err := jwt.DecodeGeneric(theJWT); err != nil {
 			return err
-		} else if existing, err := os.ReadFile(path); err != nil {
+		} else if existing, err := ioutil.ReadFile(path); err != nil {
 			return err
 		} else if existingJWT, err := jwt.DecodeGeneric(string(existing)); err != nil {
 			// skip if it can't be decoded
diff --git a/server/errors.json b/server/errors.json
index 5730766e..530f6e70 100644
--- a/server/errors.json
+++ b/server/errors.json
@@ -80,10 +80,10 @@
     "deprecates": ""
   },
   {
-    "constant": "JSClusterNoPeersErrF",
+    "constant": "JSClusterNoPeersErr",
     "code": 400,
     "error_code": 10005,
-    "description": "no suitable peers for placement: {err}",
+    "description": "no suitable peers for placement",
     "comment": "",
     "help": "",
     "url": "",
diff --git a/server/errors_gen.go b/server/errors_gen.go
index bbe50a51..ade67e4e 100644
--- a/server/errors_gen.go
+++ b/server/errors_gen.go
@@ -6,6 +6,7 @@ package main
 import (
 	"encoding/json"
 	"fmt"
+	"io/ioutil"
 	"log"
 	"os"
 	"os/exec"
@@ -33,7 +34,7 @@ const (
 {{- else }}
 	// {{ .Constant }} {{ .Description | print }}
 {{- end }}
-	{{ .Constant }} ErrorIdentifier = {{ .ErrCode }}
+	{{ .Constant }} ErrorIdentifier = {{ .ErrCode }}  
 {{ end }}
 )
 
@@ -228,7 +229,7 @@ func main() {
 	p, err := t.Parse(templ)
 	panicIfErr(err)
 
-	tf, err := os.CreateTemp("", "")
+	tf, err := ioutil.TempFile("", "")
 	panicIfErr(err)
 	defer tf.Close()
 
diff --git a/server/events.go b/server/events.go
index 31dee13f..f9fb64c7 100644
--- a/server/events.go
+++ b/server/events.go
@@ -481,9 +481,9 @@ func (s *Server) sendInternalAccountMsg(a *Account, subject string, msg interfac
 
 // Used to send an internal message with an optional reply to an arbitrary account.
 func (s *Server) sendInternalAccountMsgWithReply(a *Account, subject, reply string, hdr map[string]string, msg interface{}, echo bool) error {
-	s.mu.RLock()
+	s.mu.Lock()
 	if s.sys == nil || s.sys.sendq == nil {
-		s.mu.RUnlock()
+		s.mu.Unlock()
 		return ErrNoSysAccount
 	}
 	c := s.sys.client
@@ -494,16 +494,16 @@ func (s *Server) sendInternalAccountMsgWithReply(a *Account, subject, reply stri
 		a.mu.Unlock()
 	}
 	s.sys.sendq.push(newPubMsg(c, subject, reply, nil, hdr, msg, noCompression, echo, false))
-	s.mu.RUnlock()
+	s.mu.Unlock()
 	return nil
 }
 
 // This will queue up a message to be sent.
 // Lock should not be held.
 func (s *Server) sendInternalMsgLocked(subj, rply string, si *ServerInfo, msg interface{}) {
-	s.mu.RLock()
+	s.mu.Lock()
 	s.sendInternalMsg(subj, rply, si, msg)
-	s.mu.RUnlock()
+	s.mu.Unlock()
 }
 
 // This will queue up a message to be sent.
@@ -517,13 +517,13 @@ func (s *Server) sendInternalMsg(subj, rply string, si *ServerInfo, msg interfac
 
 // Will send an api response.
 func (s *Server) sendInternalResponse(subj string, response *ServerAPIResponse) {
-	s.mu.RLock()
+	s.mu.Lock()
 	if s.sys == nil || s.sys.sendq == nil {
-		s.mu.RUnlock()
+		s.mu.Unlock()
 		return
 	}
 	s.sys.sendq.push(newPubMsg(nil, subj, _EMPTY_, response.Server, nil, response, response.compress, false, false))
-	s.mu.RUnlock()
+	s.mu.Unlock()
 }
 
 // Used to send internal messages from other system clients to avoid no echo issues.
@@ -535,13 +535,13 @@ func (c *client) sendInternalMsg(subj, rply string, si *ServerInfo, msg interfac
 	if s == nil {
 		return
 	}
-	s.mu.RLock()
+	s.mu.Lock()
 	if s.sys == nil || s.sys.sendq == nil {
-		s.mu.RUnlock()
+		s.mu.Unlock()
 		return
 	}
 	s.sys.sendq.push(newPubMsg(c, subj, rply, si, nil, msg, noCompression, false, false))
-	s.mu.RUnlock()
+	s.mu.Unlock()
 }
 
 // Locked version of checking if events system running. Also checks server.
@@ -875,8 +875,8 @@ func (s *Server) initEventTracking() {
 			s.zReq(c, reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { return s.Jsz(&optz.JSzOptions) })
 		},
 		"HEALTHZ": func(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) {
-			optz := &EventFilterOptions{}
-			s.zReq(c, reply, msg, optz, optz, func() (interface{}, error) { return s.healthz(), nil })
+			optz := &HealthzEventOptions{}
+			s.zReq(c, reply, msg, &optz.EventFilterOptions, optz, func() (interface{}, error) { return s.healthz(&optz.HealthzOptions), nil })
 		},
 	}
 	for name, req := range monSrvc {
@@ -1433,6 +1433,12 @@ type JszEventOptions struct {
 	EventFilterOptions
 }
 
+// In the context of system events, HealthzEventOptions are options passed to Healthz
+type HealthzEventOptions struct {
+	HealthzOptions
+	EventFilterOptions
+}
+
 // returns true if the request does NOT apply to this server and can be ignored.
 // DO NOT hold the server lock when
 func (s *Server) filterRequest(fOpts *EventFilterOptions) bool {
diff --git a/server/filestore.go b/server/filestore.go
index fa4ece03..59788092 100644
--- a/server/filestore.go
+++ b/server/filestore.go
@@ -26,6 +26,7 @@ import (
 	"fmt"
 	"hash"
 	"io"
+	"io/ioutil"
 	"net"
 	"os"
 	"path/filepath"
@@ -273,7 +274,7 @@ func newFileStoreWithCreated(fcfg FileStoreConfig, cfg StreamConfig, created tim
 	} else if stat == nil || !stat.IsDir() {
 		return nil, fmt.Errorf("storage directory is not a directory")
 	}
-	tmpfile, err := os.CreateTemp(fcfg.StoreDir, "_test_")
+	tmpfile, err := ioutil.TempFile(fcfg.StoreDir, "_test_")
 	if err != nil {
 		return nil, fmt.Errorf("storage directory is not writable")
 	}
@@ -487,7 +488,7 @@ func (fs *fileStore) writeStreamMeta() error {
 		if _, err := os.Stat(keyFile); err != nil && !os.IsNotExist(err) {
 			return err
 		}
-		if err := os.WriteFile(keyFile, encrypted, defaultFilePerms); err != nil {
+		if err := ioutil.WriteFile(keyFile, encrypted, defaultFilePerms); err != nil {
 			return err
 		}
 	}
@@ -507,14 +508,14 @@ func (fs *fileStore) writeStreamMeta() error {
 		b = fs.aek.Seal(nonce, nonce, b, nil)
 	}
 
-	if err := os.WriteFile(meta, b, defaultFilePerms); err != nil {
+	if err := ioutil.WriteFile(meta, b, defaultFilePerms); err != nil {
 		return err
 	}
 	fs.hh.Reset()
 	fs.hh.Write(b)
 	checksum := hex.EncodeToString(fs.hh.Sum(nil))
 	sum := filepath.Join(fs.fcfg.StoreDir, JetStreamMetaFileSum)
-	if err := os.WriteFile(sum, []byte(checksum), defaultFilePerms); err != nil {
+	if err := ioutil.WriteFile(sum, []byte(checksum), defaultFilePerms); err != nil {
 		return err
 	}
 	return nil
@@ -598,7 +599,7 @@ func (fs *fileStore) recoverMsgBlock(fi os.FileInfo, index uint64) (*msgBlock, e
 
 	// Check if encryption is enabled.
 	if fs.prf != nil {
-		ekey, err := os.ReadFile(filepath.Join(mdir, fmt.Sprintf(keyScan, mb.index)))
+		ekey, err := ioutil.ReadFile(filepath.Join(mdir, fmt.Sprintf(keyScan, mb.index)))
 		if err != nil {
 			// We do not seem to have keys even though we should. Could be a plaintext conversion.
 			// Create the keys and we will double check below.
@@ -648,15 +649,15 @@ func (fs *fileStore) recoverMsgBlock(fi os.FileInfo, index uint64) (*msgBlock, e
 		// Undo cache from above for later.
 		mb.cache = nil
 		mb.bek.XORKeyStream(buf, buf)
-		if err := os.WriteFile(mb.mfn, buf, defaultFilePerms); err != nil {
+		if err := ioutil.WriteFile(mb.mfn, buf, defaultFilePerms); err != nil {
 			return nil, err
 		}
-		if buf, err = os.ReadFile(mb.ifn); err == nil && len(buf) > 0 {
+		if buf, err = ioutil.ReadFile(mb.ifn); err == nil && len(buf) > 0 {
 			if err := checkHeader(buf); err != nil {
 				return nil, err
 			}
 			buf = mb.aek.Seal(buf[:0], mb.nonce, buf, nil)
-			if err := os.WriteFile(mb.ifn, buf, defaultFilePerms); err != nil {
+			if err := ioutil.WriteFile(mb.ifn, buf, defaultFilePerms); err != nil {
 				return nil, err
 			}
 		}
@@ -962,7 +963,7 @@ func (fs *fileStore) recoverMsgs() error {
 	}
 
 	mdir := filepath.Join(fs.fcfg.StoreDir, msgDir)
-	fis, err := os.ReadDir(mdir)
+	fis, err := ioutil.ReadDir(mdir)
 	if err != nil {
 		return errNotReadable
 	}
@@ -972,11 +973,7 @@ func (fs *fileStore) recoverMsgs() error {
 	for _, fi := range fis {
 		var index uint64
 		if n, err := fmt.Sscanf(fi.Name(), blkScan, &index); err == nil && n == 1 {
-			finfo, err := fi.Info()
-			if err != nil {
-				return err
-			}
-			if mb, err := fs.recoverMsgBlock(finfo, index); err == nil && mb != nil {
+			if mb, err := fs.recoverMsgBlock(fi, index); err == nil && mb != nil {
 				if fs.state.FirstSeq == 0 || mb.first.seq < fs.state.FirstSeq {
 					fs.state.FirstSeq = mb.first.seq
 					fs.state.FirstTime = time.Unix(0, mb.first.ts).UTC()
@@ -1690,7 +1687,7 @@ func (fs *fileStore) genEncryptionKeysForBlock(mb *msgBlock) error {
 	if _, err := os.Stat(keyFile); err != nil && !os.IsNotExist(err) {
 		return err
 	}
-	if err := os.WriteFile(keyFile, encrypted, defaultFilePerms); err != nil {
+	if err := ioutil.WriteFile(keyFile, encrypted, defaultFilePerms); err != nil {
 		return err
 	}
 	mb.kfn = keyFile
@@ -2253,7 +2250,7 @@ func (mb *msgBlock) compact() {
 
 	// We will write to a new file and mv/rename it in case of failure.
 	mfn := filepath.Join(filepath.Join(mb.fs.fcfg.StoreDir, msgDir), fmt.Sprintf(newScan, mb.index))
-	if err := os.WriteFile(mfn, nbuf, defaultFilePerms); err != nil {
+	if err := ioutil.WriteFile(mfn, nbuf, defaultFilePerms); err != nil {
 		os.Remove(mfn)
 		return
 	}
@@ -3371,7 +3368,7 @@ func (mb *msgBlock) flushPendingMsgsLocked() (*LostStreamData, error) {
 	return fsLostData, mb.werr
 }
 
-// Lock should be held.
+//  Lock should be held.
 func (mb *msgBlock) clearLoading() {
 	mb.loading = false
 }
@@ -4045,7 +4042,7 @@ func (mb *msgBlock) writeIndexInfoLocked() error {
 
 // readIndexInfo will read in the index information for the message block.
 func (mb *msgBlock) readIndexInfo() error {
-	buf, err := os.ReadFile(mb.ifn)
+	buf, err := ioutil.ReadFile(mb.ifn)
 	if err != nil {
 		return err
 	}
@@ -4516,7 +4513,7 @@ func (fs *fileStore) Compact(seq uint64) (uint64, error) {
 				smb.bek = bek
 				smb.bek.XORKeyStream(nbuf, nbuf)
 			}
-			if err = os.WriteFile(smb.mfn, nbuf, defaultFilePerms); err != nil {
+			if err = ioutil.WriteFile(smb.mfn, nbuf, defaultFilePerms); err != nil {
 				goto SKIP
 			}
 			smb.clearCacheAndOffset()
@@ -4681,7 +4678,7 @@ func (mb *msgBlock) closeAndKeepIndex() {
 		mb.mfd.Truncate(0)
 	} else {
 		// We were closed, so just write out an empty file.
-		os.WriteFile(mb.mfn, nil, defaultFilePerms)
+		ioutil.WriteFile(mb.mfn, nil, defaultFilePerms)
 	}
 	// Make sure to write the index file so we can remember last seq and ts.
 	mb.writeIndexInfoLocked()
@@ -4850,7 +4847,7 @@ func (mb *msgBlock) readPerSubjectInfo() error {
 		minFileSize   = 24
 	)
 
-	buf, err := os.ReadFile(mb.sfn)
+	buf, err := ioutil.ReadFile(mb.sfn)
 
 	if err != nil || len(buf) < minFileSize || checkHeader(buf) != nil {
 		return mb.generatePerSubjectInfo()
@@ -4929,7 +4926,7 @@ func (mb *msgBlock) writePerSubjectInfo() error {
 	// Now copy over checksum from the block itself, this allows us to know if we are in sync.
 	b.Write(mb.lchk[:])
 
-	return os.WriteFile(mb.sfn, b.Bytes(), defaultFilePerms)
+	return ioutil.WriteFile(mb.sfn, b.Bytes(), defaultFilePerms)
 }
 
 // Close the message block.
@@ -5125,7 +5122,7 @@ func (fs *fileStore) streamSnapshot(w io.WriteCloser, state *StreamState, includ
 			mb.writeIndexInfo()
 		}
 		mb.mu.Lock()
-		buf, err := os.ReadFile(mb.ifn)
+		buf, err := ioutil.ReadFile(mb.ifn)
 		if err != nil {
 			mb.mu.Unlock()
 			writeErr(fmt.Sprintf("Could not read message block [%d] index file: %v", mb.index, err))
@@ -5164,7 +5161,7 @@ func (fs *fileStore) streamSnapshot(w io.WriteCloser, state *StreamState, includ
 		}
 		// Make sure we snapshot the per subject info.
 		mb.writePerSubjectInfo()
-		buf, err = os.ReadFile(mb.sfn)
+		buf, err = ioutil.ReadFile(mb.sfn)
 		// If not there that is ok and not fatal.
 		if err == nil && writeFile(msgPre+fmt.Sprintf(fssScan, mb.index), buf) != nil {
 			mb.mu.Unlock()
@@ -5336,7 +5333,7 @@ func (fs *fileStore) ConsumerStore(name string, cfg *ConsumerConfig) (ConsumerSt
 
 	// Check for encryption.
 	if o.prf != nil {
-		if ekey, err := os.ReadFile(filepath.Join(odir, JetStreamMetaFileKey)); err == nil {
+		if ekey, err := ioutil.ReadFile(filepath.Join(odir, JetStreamMetaFileKey)); err == nil {
 			// Recover key encryption key.
 			rb, err := fs.prf([]byte(fs.cfg.Name + tsep + o.name))
 			if err != nil {
@@ -5383,9 +5380,9 @@ func (fs *fileStore) ConsumerStore(name string, cfg *ConsumerConfig) (ConsumerSt
 				return nil, err
 			}
 			// Redo the state file as well here if we have one and we can tell it was plaintext.
-			if buf, err := os.ReadFile(o.ifn); err == nil {
+			if buf, err := ioutil.ReadFile(o.ifn); err == nil {
 				if _, err := decodeConsumerState(buf); err == nil {
-					if err := os.WriteFile(o.ifn, o.encryptState(buf), defaultFilePerms); err != nil {
+					if err := ioutil.WriteFile(o.ifn, o.encryptState(buf), defaultFilePerms); err != nil {
 						if didCreate {
 							os.RemoveAll(odir)
 						}
@@ -5777,7 +5774,7 @@ func (o *consumerFileStore) writeState(buf []byte) error {
 
 	// Lock not held here but we do limit number of outstanding calls that could block OS threads.
 	<-dios
-	err := os.WriteFile(ifn, buf, defaultFilePerms)
+	err := ioutil.WriteFile(ifn, buf, defaultFilePerms)
 	dios <- struct{}{}
 
 	o.mu.Lock()
@@ -5817,7 +5814,7 @@ func (cfs *consumerFileStore) writeConsumerMeta() error {
 		if _, err := os.Stat(keyFile); err != nil && !os.IsNotExist(err) {
 			return err
 		}
-		if err := os.WriteFile(keyFile, encrypted, defaultFilePerms); err != nil {
+		if err := ioutil.WriteFile(keyFile, encrypted, defaultFilePerms); err != nil {
 			return err
 		}
 	}
@@ -5833,14 +5830,14 @@ func (cfs *consumerFileStore) writeConsumerMeta() error {
 		b = cfs.aek.Seal(nonce, nonce, b, nil)
 	}
 
-	if err := os.WriteFile(meta, b, defaultFilePerms); err != nil {
+	if err := ioutil.WriteFile(meta, b, defaultFilePerms); err != nil {
 		return err
 	}
 	cfs.hh.Reset()
 	cfs.hh.Write(b)
 	checksum := hex.EncodeToString(cfs.hh.Sum(nil))
 	sum := filepath.Join(cfs.odir, JetStreamMetaFileSum)
-	if err := os.WriteFile(sum, []byte(checksum), defaultFilePerms); err != nil {
+	if err := ioutil.WriteFile(sum, []byte(checksum), defaultFilePerms); err != nil {
 		return err
 	}
 	return nil
@@ -5912,7 +5909,7 @@ func (o *consumerFileStore) State() (*ConsumerState, error) {
 	}
 
 	// Read the state in here from disk..
-	buf, err := os.ReadFile(o.ifn)
+	buf, err := ioutil.ReadFile(o.ifn)
 	if err != nil && !os.IsNotExist(err) {
 		return nil, err
 	}
@@ -6092,7 +6089,7 @@ func (o *consumerFileStore) Stop() error {
 	if len(buf) > 0 {
 		o.waitOnFlusher()
 		<-dios
-		err = os.WriteFile(ifn, buf, defaultFilePerms)
+		err = ioutil.WriteFile(ifn, buf, defaultFilePerms)
 		dios <- struct{}{}
 	}
 	return err
@@ -6206,7 +6203,7 @@ func (ts *templateFileStore) Store(t *streamTemplate) error {
 	if err != nil {
 		return err
 	}
-	if err := os.WriteFile(meta, b, defaultFilePerms); err != nil {
+	if err := ioutil.WriteFile(meta, b, defaultFilePerms); err != nil {
 		return err
 	}
 	// FIXME(dlc) - Do checksum
@@ -6214,7 +6211,7 @@ func (ts *templateFileStore) Store(t *streamTemplate) error {
 	ts.hh.Write(b)
 	checksum := hex.EncodeToString(ts.hh.Sum(nil))
 	sum := filepath.Join(dir, JetStreamMetaFileSum)
-	if err := os.WriteFile(sum, []byte(checksum), defaultFilePerms); err != nil {
+	if err := ioutil.WriteFile(sum, []byte(checksum), defaultFilePerms); err != nil {
 		return err
 	}
 	return nil
diff --git a/server/gateway.go b/server/gateway.go
index 98439ac1..8e4939d8 100644
--- a/server/gateway.go
+++ b/server/gateway.go
@@ -3096,7 +3096,7 @@ func (c *client) gatewaySwitchAccountToSendAllSubs(e *insie, accName string) {
 // If `client` is nil, the mapping is stored in the client's account's gwReplyMapping
 // structure. Account lock will be explicitly acquired.
 // This is a server receiver because we use a timer interval that is avail in
-// Server.gateway object.
+/// Server.gateway object.
 func (s *Server) trackGWReply(c *client, acc *Account, reply, routedReply []byte) {
 	var l sync.Locker
 	var g *gwReplyMapping
diff --git a/server/jetstream.go b/server/jetstream.go
index f96c3b59..cd2420e6 100644
--- a/server/jetstream.go
+++ b/server/jetstream.go
@@ -21,6 +21,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"math"
 	"os"
 	"path/filepath"
@@ -93,22 +94,20 @@ type JetStreamAPIStats struct {
 // This is for internal accounting for JetStream for this server.
 type jetStream struct {
 	// These are here first because of atomics on 32bit systems.
-	apiInflight   int64
-	apiTotal      int64
-	apiErrors     int64
-	memReserved   int64
-	storeReserved int64
-	memUsed       int64
-	storeUsed     int64
-	clustered     int32
-	mu            sync.RWMutex
-	srv           *Server
-	config        JetStreamConfig
-	cluster       *jetStreamCluster
-	accounts      map[string]*jsAccount
-	apiSubs       *Sublist
-	// System level request to purge a stream move
-	accountPurge   *subscription
+	apiInflight    int64
+	apiTotal       int64
+	apiErrors      int64
+	memReserved    int64
+	storeReserved  int64
+	memUsed        int64
+	storeUsed      int64
+	clustered      int32
+	mu             sync.RWMutex
+	srv            *Server
+	config         JetStreamConfig
+	cluster        *jetStreamCluster
+	accounts       map[string]*jsAccount
+	apiSubs        *Sublist
 	metaRecovering bool
 	standAlone     bool
 	disabled       bool
@@ -267,14 +266,14 @@ func (s *Server) decryptMeta(ekey, buf []byte, acc, context string) ([]byte, err
 // Check to make sure directory has the jetstream directory.
 // We will have it properly configured here now regardless, so need to look inside.
 func (s *Server) checkStoreDir(cfg *JetStreamConfig) error {
-	fis, _ := os.ReadDir(cfg.StoreDir)
+	fis, _ := ioutil.ReadDir(cfg.StoreDir)
 	// If we have nothing underneath us, could be just starting new, but if we see this we can check.
 	if len(fis) != 0 {
 		return nil
 	}
 	// Let's check the directory above. If it has us 'jetstream' but also other stuff that we can
 	// identify as accounts then we can fix.
-	fis, _ = os.ReadDir(filepath.Dir(cfg.StoreDir))
+	fis, _ = ioutil.ReadDir(filepath.Dir(cfg.StoreDir))
 	// If just one that is us 'jetstream' and all is ok.
 	if len(fis) == 1 {
 		return nil
@@ -343,7 +342,7 @@ func (s *Server) enableJetStream(cfg JetStreamConfig) error {
 		if stat == nil || !stat.IsDir() {
 			return fmt.Errorf("storage directory is not a directory")
 		}
-		tmpfile, err := os.CreateTemp(cfg.StoreDir, "_test_")
+		tmpfile, err := ioutil.TempFile(cfg.StoreDir, "_test_")
 		if err != nil {
 			return fmt.Errorf("storage directory is not writable")
 		}
@@ -690,21 +689,6 @@ func (s *Server) configAllJetStreamAccounts() error {
 		return nil
 	}
 
-	if s.sys != nil {
-		// clustered stream removal will perform this cleanup as well
-		// this is mainly for initial cleanup
-		saccName := s.sys.account.Name
-		accStoreDirs, _ := os.ReadDir(js.config.StoreDir)
-		for _, acc := range accStoreDirs {
-			if accName := acc.Name(); accName != saccName {
-				// no op if not empty
-				accDir := filepath.Join(js.config.StoreDir, accName)
-				os.Remove(filepath.Join(accDir, streamsDir))
-				os.Remove(accDir)
-			}
-		}
-	}
-
 	var jsAccounts []*Account
 	s.accounts.Range(func(k, v interface{}) bool {
 		jsAccounts = append(jsAccounts, v.(*Account))
@@ -723,7 +707,7 @@ func (s *Server) configAllJetStreamAccounts() error {
 
 	// Now walk all the storage we have and resolve any accounts that we did not process already.
 	// This is important in resolver/operator models.
-	fis, _ := os.ReadDir(js.config.StoreDir)
+	fis, _ := ioutil.ReadDir(js.config.StoreDir)
 	for _, fi := range fis {
 		if accName := fi.Name(); accName != _EMPTY_ {
 			// Only load up ones not already loaded since they are processed above.
@@ -757,12 +741,6 @@ func (js *jetStream) setJetStreamStandAlone(isStandAlone bool) {
 	js.mu.Lock()
 	defer js.mu.Unlock()
 	js.standAlone = isStandAlone
-
-	if isStandAlone {
-		js.accountPurge, _ = js.srv.systemSubscribe(JSApiAccountPurge, _EMPTY_, false, nil, js.srv.jsLeaderAccountPurgeRequest)
-	} else if js.accountPurge != nil {
-		js.srv.sysUnsubscribe(js.accountPurge)
-	}
 }
 
 // JetStreamEnabled reports if jetstream is enabled for this server.
@@ -894,20 +872,14 @@ func (s *Server) shutdownJetStream() {
 	var _a [512]*Account
 	accounts := _a[:0]
 
-	js.mu.Lock()
+	js.mu.RLock()
 	// Collect accounts.
 	for _, jsa := range js.accounts {
 		if a := jsa.acc(); a != nil {
 			accounts = append(accounts, a)
 		}
 	}
-	accPurgeSub := js.accountPurge
-	js.accountPurge = nil
-	js.mu.Unlock()
-
-	if accPurgeSub != nil {
-		s.sysUnsubscribe(accPurgeSub)
-	}
+	js.mu.RUnlock()
 
 	for _, a := range accounts {
 		a.removeJetStream()
@@ -976,9 +948,9 @@ func (s *Server) JetStreamReservedResources() (int64, int64, error) {
 }
 
 func (s *Server) getJetStream() *jetStream {
-	s.mu.RLock()
+	s.mu.Lock()
 	js := s.js
-	s.mu.RUnlock()
+	s.mu.Unlock()
 	return js
 }
 
@@ -1080,8 +1052,7 @@ func (a *Account) EnableJetStream(limits map[string]JetStreamAccountLimits) erro
 		// Just need to make sure we can write to the directory.
 		// Remove the directory will create later if needed.
 		os.RemoveAll(sdir)
-		// when empty remove parent directory, which may have been created as well
-		os.Remove(jsa.storeDir)
+
 	} else {
 		// Restore any state here.
 		s.Debugf("Recovering JetStream state for account %q", a.Name)
@@ -1096,11 +1067,11 @@ func (a *Account) EnableJetStream(limits map[string]JetStreamAccountLimits) erro
 		if err != nil {
 			return err
 		}
-		fis, _ := os.ReadDir(tdir)
+		fis, _ := ioutil.ReadDir(tdir)
 		for _, fi := range fis {
 			metafile := filepath.Join(tdir, fi.Name(), JetStreamMetaFile)
 			metasum := filepath.Join(tdir, fi.Name(), JetStreamMetaFileSum)
-			buf, err := os.ReadFile(metafile)
+			buf, err := ioutil.ReadFile(metafile)
 			if err != nil {
 				s.Warnf("  Error reading StreamTemplate metafile %q: %v", metasum, err)
 				continue
@@ -1109,7 +1080,7 @@ func (a *Account) EnableJetStream(limits map[string]JetStreamAccountLimits) erro
 				s.Warnf("  Missing StreamTemplate checksum for %q", metasum)
 				continue
 			}
-			sum, err := os.ReadFile(metasum)
+			sum, err := ioutil.ReadFile(metasum)
 			if err != nil {
 				s.Warnf("  Error reading StreamTemplate checksum %q: %v", metasum, err)
 				continue
@@ -1142,7 +1113,7 @@ func (a *Account) EnableJetStream(limits map[string]JetStreamAccountLimits) erro
 	var consumers []*ce
 
 	// Now recover the streams.
-	fis, _ := os.ReadDir(sdir)
+	fis, _ := ioutil.ReadDir(sdir)
 	for _, fi := range fis {
 		mdir := filepath.Join(sdir, fi.Name())
 		key := sha256.Sum256([]byte(fi.Name()))
@@ -1156,7 +1127,7 @@ func (a *Account) EnableJetStream(limits map[string]JetStreamAccountLimits) erro
 			s.Warnf("  Missing stream metafile for %q", metafile)
 			continue
 		}
-		buf, err := os.ReadFile(metafile)
+		buf, err := ioutil.ReadFile(metafile)
 		if err != nil {
 			s.Warnf("  Error reading metafile %q: %v", metafile, err)
 			continue
@@ -1165,7 +1136,7 @@ func (a *Account) EnableJetStream(limits map[string]JetStreamAccountLimits) erro
 			s.Warnf("  Missing stream checksum file %q", metasum)
 			continue
 		}
-		sum, err := os.ReadFile(metasum)
+		sum, err := ioutil.ReadFile(metasum)
 		if err != nil {
 			s.Warnf("  Error reading Stream metafile checksum %q: %v", metasum, err)
 			continue
@@ -1178,7 +1149,7 @@ func (a *Account) EnableJetStream(limits map[string]JetStreamAccountLimits) erro
 		}
 
 		// Check if we are encrypted.
-		if key, err := os.ReadFile(filepath.Join(mdir, JetStreamMetaFileKey)); err == nil {
+		if key, err := ioutil.ReadFile(filepath.Join(mdir, JetStreamMetaFileKey)); err == nil {
 			s.Debugf("  Stream metafile is encrypted, reading encrypted keyfile")
 			if len(key) != metaKeySize {
 				s.Warnf("  Bad stream encryption key length of %d", len(key))
@@ -1251,7 +1222,7 @@ func (a *Account) EnableJetStream(limits map[string]JetStreamAccountLimits) erro
 	}
 
 	for _, e := range consumers {
-		ofis, _ := os.ReadDir(e.odir)
+		ofis, _ := ioutil.ReadDir(e.odir)
 		if len(ofis) > 0 {
 			s.Noticef("  Recovering %d consumers for stream - '%s > %s'", len(ofis), e.mset.accName(), e.mset.name())
 		}
@@ -1262,7 +1233,7 @@ func (a *Account) EnableJetStream(limits map[string]JetStreamAccountLimits) erro
 				s.Warnf("    Missing consumer metafile %q", metafile)
 				continue
 			}
-			buf, err := os.ReadFile(metafile)
+			buf, err := ioutil.ReadFile(metafile)
 			if err != nil {
 				s.Warnf("    Error reading consumer metafile %q: %v", metafile, err)
 				continue
@@ -1273,7 +1244,7 @@ func (a *Account) EnableJetStream(limits map[string]JetStreamAccountLimits) erro
 			}
 
 			// Check if we are encrypted.
-			if key, err := os.ReadFile(filepath.Join(e.odir, ofi.Name(), JetStreamMetaFileKey)); err == nil {
+			if key, err := ioutil.ReadFile(filepath.Join(e.odir, ofi.Name(), JetStreamMetaFileKey)); err == nil {
 				s.Debugf("  Consumer metafile is encrypted, reading encrypted keyfile")
 				// Decode the buffer before proceeding.
 				if buf, err = s.decryptMeta(key, buf, a.Name, e.mset.name()+tsep+ofi.Name()); err != nil {
diff --git a/server/jetstream_api.go b/server/jetstream_api.go
index b583ead8..e5849b51 100644
--- a/server/jetstream_api.go
+++ b/server/jetstream_api.go
@@ -18,6 +18,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"math/rand"
 	"os"
 	"path/filepath"
@@ -123,11 +124,6 @@ const (
 	JSDirectMsgGet  = "$JS.API.DIRECT.GET.*"
 	JSDirectMsgGetT = "$JS.API.DIRECT.GET.%s"
 
-	// This is a direct version of get last by subject, which will be the dominant pattern for KV access once 2.9 is released.
-	// The stream and the key will be part of the subject to allow for no-marshal payloads and subject based security permissions.
-	JSDirectGetLastBySubject  = "$JS.API.DIRECT.GET.*.>"
-	JSDirectGetLastBySubjectT = "$JS.API.DIRECT.GET.%s.%s"
-
 	// jsDirectGetPre
 	jsDirectGetPre = "$JS.API.DIRECT.GET"
 
@@ -194,12 +190,6 @@ const (
 	// Will return JSON response.
 	JSApiRemoveServer = "$JS.API.SERVER.REMOVE"
 
-	// JSApiAccountPurge is the endpoint to purge the js content of an account
-	// Only works from system account.
-	// Will return JSON response.
-	JSApiAccountPurge  = "$JS.API.ACCOUNT.PURGE.*"
-	JSApiAccountPurgeT = "$JS.API.ACCOUNT.PURGE.%s"
-
 	// JSApiServerStreamMove is the endpoint to move streams off a server
 	// Only works from system account.
 	// Will return JSON response.
@@ -310,10 +300,8 @@ func generateJSMappingTable(domain string) map[string]string {
 		"INFO":       JSApiAccountInfo,
 		"STREAM.>":   "$JS.API.STREAM.>",
 		"CONSUMER.>": "$JS.API.CONSUMER.>",
-		"DIRECT.>":   "$JS.API.DIRECT.>",
 		"META.>":     "$JS.API.META.>",
 		"SERVER.>":   "$JS.API.SERVER.>",
-		"ACCOUNT.>":  "$JS.API.ACCOUNT.>",
 		"$KV.>":      "$KV.>",
 		"$OBJ.>":     "$OBJ.>",
 	} {
@@ -598,14 +586,6 @@ type JSApiMetaServerStreamMoveRequest struct {
 	Tags []string `json:"tags,omitempty"`
 }
 
-const JSApiAccountPurgeResponseType = "io.nats.jetstream.api.v1.account_purge_response"
-
-// JSApiAccountPurgeResponse is the response to a purge request in the meta group.
-type JSApiAccountPurgeResponse struct {
-	ApiResponse
-	Initiated bool `json:"initiated,omitempty"`
-}
-
 // JSApiMsgGetRequest get a message request.
 type JSApiMsgGetRequest struct {
 	Seq     uint64 `json:"seq,omitempty"`
@@ -2357,7 +2337,7 @@ func (s *Server) jsLeaderServerStreamMoveRequest(sub *subscription, c *client, _
 		cfg.Placement.Tags = append(cfg.Placement.Tags, req.Tags...)
 	}
 
-	peers, e := cc.selectPeerGroup(cfg.Replicas+1, currCluster, &cfg, currPeers, 1)
+	peers := cc.selectPeerGroup(cfg.Replicas+1, currCluster, &cfg, currPeers, 1)
 	if len(peers) <= cfg.Replicas {
 		// since expanding in the same cluster did not yield a result, try in different cluster
 		peers = nil
@@ -2369,18 +2349,16 @@ func (s *Server) jsLeaderServerStreamMoveRequest(sub *subscription, c *client, _
 			}
 			return true
 		})
-		errs := selectPeerErrors{e}
 		for cluster := range clusters {
-			newPeers, _ := cc.selectPeerGroup(cfg.Replicas, cluster, &cfg, nil, 0)
+			newPeers := cc.selectPeerGroup(cfg.Replicas, cluster, &cfg, nil, 0)
 			if len(newPeers) >= cfg.Replicas {
 				peers = append([]string{}, currPeers...)
 				peers = append(peers, newPeers[:cfg.Replicas]...)
 				break
 			}
-			errs = append(errs, e)
 		}
 		if peers == nil {
-			resp.Error = NewJSClusterNoPeersError(&errs)
+			resp.Error = NewJSClusterNoPeersError()
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -2472,89 +2450,6 @@ func (s *Server) jsLeaderServerStreamCancelMoveRequest(sub *subscription, c *cli
 	s.jsClusteredStreamUpdateRequest(&ciNew, targetAcc.(*Account), subject, reply, rmsg, &cfg, peers)
 }
 
-// Request to have an account purged
-func (s *Server) jsLeaderAccountPurgeRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
-	if c == nil || !s.JetStreamEnabled() {
-		return
-	}
-
-	ci, acc, _, msg, err := s.getRequestInfo(c, rmsg)
-	if err != nil {
-		s.Warnf(badAPIRequestT, msg)
-		return
-	}
-
-	js := s.getJetStream()
-	if js == nil {
-		return
-	}
-
-	accName := tokenAt(subject, 5)
-
-	var resp = JSApiAccountPurgeResponse{ApiResponse: ApiResponse{Type: JSApiAccountPurgeResponseType}}
-
-	if !s.JetStreamIsClustered() {
-		var streams []*stream
-		var ac *Account
-		if ac, err = s.lookupAccount(accName); err == nil && ac != nil {
-			streams = ac.streams()
-		}
-
-		s.Noticef("Purge request for account %s (streams: %d, hasAccount: %t)",
-			accName, len(streams), ac != nil)
-
-		for _, mset := range streams {
-			err := mset.delete()
-			if err != nil {
-				resp.Error = NewJSStreamDeleteError(err)
-				s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
-				return
-			}
-		}
-		if err := os.RemoveAll(filepath.Join(js.config.StoreDir, accName)); err != nil {
-			resp.Error = NewJSStreamGeneralError(err)
-			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
-			return
-		}
-		resp.Initiated = true
-		s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
-		return
-	}
-
-	_, cc := s.getJetStreamCluster()
-	if cc == nil || cc.meta == nil || !cc.isLeader() {
-		return
-	}
-
-	if js.isMetaRecovering() {
-		// While in recovery mode, the data structures are not fully initialized
-		resp.Error = NewJSClusterNotAvailError()
-		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
-		return
-	}
-
-	js.mu.RLock()
-	ns, nc := 0, 0
-	streams, hasAccount := cc.streams[accName]
-	for _, osa := range streams {
-		for _, oca := range osa.consumers {
-			oca.deleted = true
-			ca := &consumerAssignment{Group: oca.Group, Stream: oca.Stream, Name: oca.Name, Config: oca.Config, Subject: subject, Client: oca.Client}
-			cc.meta.Propose(encodeDeleteConsumerAssignment(ca))
-			nc++
-		}
-		sa := &streamAssignment{Group: osa.Group, Config: osa.Config, Subject: subject, Client: osa.Client}
-		cc.meta.Propose(encodeDeleteStreamAssignment(sa))
-		ns++
-	}
-	js.mu.RUnlock()
-
-	s.Noticef("Purge request for account %s (streams: %d, consumer: %d, hasAccount: %t)", accName, ns, nc, hasAccount)
-
-	resp.Initiated = true
-	s.sendAPIResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
-}
-
 // Request to have the meta leader stepdown.
 // These will only be received the the meta leaders, so less checking needed.
 func (s *Server) jsLeaderStepDownRequest(sub *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
@@ -2610,7 +2505,7 @@ func (s *Server) jsLeaderStepDownRequest(sub *subscription, c *client, _ *Accoun
 			}
 		}
 		if len(peers) == 0 {
-			resp.Error = NewJSClusterNoPeersError(fmt.Errorf("no replacement peer connected"))
+			resp.Error = NewJSClusterNoPeersError()
 			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
 			return
 		}
@@ -3189,7 +3084,7 @@ func (s *Server) processStreamRestore(ci *ClientInfo, acc *Account, cfg *StreamC
 		}
 	}
 
-	tfile, err := os.CreateTemp(snapDir, "js-restore-")
+	tfile, err := ioutil.TempFile(snapDir, "js-restore-")
 	if err != nil {
 		resp.Error = NewJSTempStorageFailedError()
 		s.sendAPIErrResponse(ci, acc, subject, reply, msg, s.jsonResponse(&resp))
diff --git a/server/jetstream_cluster.go b/server/jetstream_cluster.go
index b9530142..aa1842d7 100644
--- a/server/jetstream_cluster.go
+++ b/server/jetstream_cluster.go
@@ -21,7 +21,6 @@ import (
 	"fmt"
 	"math"
 	"math/rand"
-	"os"
 	"path/filepath"
 	"reflect"
 	"sort"
@@ -915,12 +914,12 @@ func (js *jetStream) monitorCluster() {
 					js.clearMetaRecovering()
 
 					// Process any removes that are still valid after recovery.
-					for _, ca := range rm.consumers {
-						js.processConsumerRemoval(ca)
-					}
 					for _, sa := range rm.streams {
 						js.processStreamRemoval(sa)
 					}
+					for _, ca := range rm.consumers {
+						js.processConsumerRemoval(ca)
+					}
 					// Clear.
 					rm = nil
 					s.Debugf("Recovered JetStream cluster metadata")
@@ -1078,15 +1077,16 @@ func (js *jetStream) metaSnapshot() []byte {
 }
 
 func (js *jetStream) applyMetaSnapshot(buf []byte) error {
+	if len(buf) == 0 {
+		return nil
+	}
+	jse, err := s2.Decode(nil, buf)
+	if err != nil {
+		return err
+	}
 	var wsas []writeableStreamAssignment
-	if len(buf) != 0 {
-		jse, err := s2.Decode(nil, buf)
-		if err != nil {
-			return err
-		}
-		if err = json.Unmarshal(jse, &wsas); err != nil {
-			return err
-		}
+	if err = json.Unmarshal(jse, &wsas); err != nil {
+		return err
 	}
 
 	// Build our new version here outside of js.
@@ -1146,8 +1146,6 @@ func (js *jetStream) applyMetaSnapshot(buf []byte) error {
 		}
 	}
 	isRecovering := js.metaRecovering
-	storeDir := js.config.StoreDir
-	srv := js.srv
 	js.mu.Unlock()
 
 	// Do removals first.
@@ -1185,20 +1183,6 @@ func (js *jetStream) applyMetaSnapshot(buf []byte) error {
 		js.processConsumerAssignment(ca)
 	}
 
-	// Delete directories not part of snapshot
-	sysAcc := srv.SystemAccount().GetName()
-	if de, err := os.ReadDir(storeDir); err == nil {
-		for _, entry := range de {
-			acc := entry.Name()
-			if acc == sysAcc {
-				continue
-			}
-			if _, found := streams[acc]; !found {
-				os.RemoveAll(filepath.Join(storeDir, acc))
-			}
-		}
-	}
-
 	return nil
 }
 
@@ -2589,23 +2573,6 @@ func (js *jetStream) processStreamAssignment(sa *streamAssignment) bool {
 		return false
 	}
 
-	js.mu.Lock()
-	accStreams := cc.streams[accName]
-	if accStreams == nil {
-		accStreams = make(map[string]*streamAssignment)
-	} else if osa := accStreams[stream]; osa != nil && osa != sa {
-		// Copy over private existing state from former SA.
-		sa.Group.node = osa.Group.node
-		sa.consumers = osa.consumers
-		sa.responded = osa.responded
-		sa.err = osa.err
-	}
-
-	// Update our state.
-	accStreams[stream] = sa
-	cc.streams[accName] = accStreams
-	js.mu.Unlock()
-
 	acc, err := s.LookupAccount(accName)
 	if err != nil {
 		ll := fmt.Sprintf("Account [%s] lookup for stream create failed: %v", accName, err)
@@ -2625,6 +2592,23 @@ func (js *jetStream) processStreamAssignment(sa *streamAssignment) bool {
 		return false
 	}
 
+	js.mu.Lock()
+	accStreams := cc.streams[acc.Name]
+	if accStreams == nil {
+		accStreams = make(map[string]*streamAssignment)
+	} else if osa := accStreams[stream]; osa != nil && osa != sa {
+		// Copy over private existing state from former SA.
+		sa.Group.node = osa.Group.node
+		sa.consumers = osa.consumers
+		sa.responded = osa.responded
+		sa.err = osa.err
+	}
+
+	// Update our state.
+	accStreams[stream] = sa
+	cc.streams[acc.Name] = accStreams
+	js.mu.Unlock()
+
 	var didRemove bool
 
 	// Check if this is for us..
@@ -2667,7 +2651,11 @@ func (js *jetStream) processUpdateStreamAssignment(sa *streamAssignment) {
 		return
 	}
 
-	accName := sa.Client.serviceAccount()
+	acc, err := s.LookupAccount(sa.Client.serviceAccount())
+	if err != nil {
+		// TODO(dlc) - log error
+		return
+	}
 	stream := sa.Config.Name
 
 	js.mu.Lock()
@@ -2682,7 +2670,7 @@ func (js *jetStream) processUpdateStreamAssignment(sa *streamAssignment) {
 		isMember = sa.Group.isMember(ourID)
 	}
 
-	accStreams := cc.streams[accName]
+	accStreams := cc.streams[acc.Name]
 	if accStreams == nil {
 		js.mu.Unlock()
 		return
@@ -2705,7 +2693,7 @@ func (js *jetStream) processUpdateStreamAssignment(sa *streamAssignment) {
 
 	// Update our state.
 	accStreams[stream] = sa
-	cc.streams[accName] = accStreams
+	cc.streams[acc.Name] = accStreams
 
 	// Make sure we respond if we are a member.
 	if isMember {
@@ -2716,12 +2704,6 @@ func (js *jetStream) processUpdateStreamAssignment(sa *streamAssignment) {
 	}
 	js.mu.Unlock()
 
-	acc, err := s.LookupAccount(accName)
-	if err != nil {
-		s.Warnf("Update Stream Account %s, error on lookup: %v", accName, err)
-		return
-	}
-
 	// Check if this is for us..
 	if isMember {
 		js.processClusterUpdateStream(acc, osa, sa)
@@ -3068,8 +3050,7 @@ func (js *jetStream) processClusterDeleteStream(sa *streamAssignment, isMember,
 	}
 	js.mu.RLock()
 	s := js.srv
-	node := sa.Group.node
-	hadLeader := node == nil || node.GroupLeader() != noLeader
+	hadLeader := sa.Group.node == nil || sa.Group.node.GroupLeader() != noLeader
 	offline := s.allPeersOffline(sa.Group)
 	var isMetaLeader bool
 	if cc := js.cluster; cc != nil {
@@ -3077,7 +3058,6 @@ func (js *jetStream) processClusterDeleteStream(sa *streamAssignment, isMember,
 	}
 	js.mu.RUnlock()
 
-	stopped := false
 	var resp = JSApiStreamDeleteResponse{ApiResponse: ApiResponse{Type: JSApiStreamDeleteResponseType}}
 	var err error
 	var acc *Account
@@ -3086,37 +3066,14 @@ func (js *jetStream) processClusterDeleteStream(sa *streamAssignment, isMember,
 	if acc, _ = s.LookupAccount(sa.Client.serviceAccount()); acc != nil {
 		if mset, _ := acc.lookupStream(sa.Config.Name); mset != nil {
 			err = mset.stop(true, wasLeader)
-			stopped = true
 		}
 	}
 
 	// Always delete the node if present.
-	if node != nil {
-		node.Delete()
+	if sa.Group.node != nil {
+		sa.Group.node.Delete()
 	}
 
-	// This is a stop gap cleanup in case
-	// 1) the account does not exist (and mset couldn't be stopped) and/or
-	// 2) node was nil (and couldn't be deleted)
-	if !stopped || node == nil {
-		if sacc := s.SystemAccount(); sacc != nil {
-			os.RemoveAll(filepath.Join(js.config.StoreDir, sacc.GetName(), defaultStoreDirName, sa.Group.Name))
-			// cleanup dependent consumer groups
-			if !stopped {
-				for _, ca := range sa.consumers {
-					os.RemoveAll(filepath.Join(js.config.StoreDir, sacc.GetName(), defaultStoreDirName, ca.Group.Name))
-				}
-			}
-		}
-	}
-	accDir := filepath.Join(js.config.StoreDir, sa.Client.serviceAccount())
-	streamDir := filepath.Join(accDir, streamsDir)
-	os.RemoveAll(filepath.Join(streamDir, sa.Config.Name))
-
-	// no op if not empty
-	os.Remove(streamDir)
-	os.Remove(accDir)
-
 	// Normally we want only the leader to respond here, but if we had no leader then all members will respond to make
 	// sure we get feedback to the user.
 	if !isMember || (hadLeader && !wasLeader) {
@@ -3126,11 +3083,6 @@ func (js *jetStream) processClusterDeleteStream(sa *streamAssignment, isMember,
 		}
 	}
 
-	// Do not respond if the account does not exist any longer
-	if acc == nil {
-		return
-	}
-
 	if err != nil {
 		resp.Error = NewJSStreamGeneralError(err, Unless(err))
 		s.sendAPIErrResponse(sa.Client, acc, sa.Subject, sa.Reply, _EMPTY_, s.jsonResponse(resp))
@@ -3160,6 +3112,26 @@ func (js *jetStream) processConsumerAssignment(ca *consumerAssignment) {
 		return
 	}
 
+	acc, err := s.LookupAccount(accName)
+	if err != nil {
+		ll := fmt.Sprintf("Account [%s] lookup for consumer create failed: %v", accName, err)
+		if isMember {
+			// If we can not lookup the account and we are a member, send this result back to the metacontroller leader.
+			result := &consumerAssignmentResult{
+				Account:  accName,
+				Stream:   stream,
+				Consumer: consumerName,
+				Response: &JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}},
+			}
+			result.Response.Error = NewJSNoAccountError()
+			s.sendInternalMsgLocked(consumerAssignmentSubj, _EMPTY_, nil, result)
+			s.Warnf(ll)
+		} else {
+			s.Debugf(ll)
+		}
+		return
+	}
+
 	sa := js.streamAssignment(accName, stream)
 	if sa == nil {
 		s.Debugf("Consumer create failed, could not locate stream '%s > %s'", accName, stream)
@@ -3194,26 +3166,6 @@ func (js *jetStream) processConsumerAssignment(ca *consumerAssignment) {
 	sa.consumers[ca.Name] = ca
 	js.mu.Unlock()
 
-	acc, err := s.LookupAccount(accName)
-	if err != nil {
-		ll := fmt.Sprintf("Account [%s] lookup for consumer create failed: %v", accName, err)
-		if isMember {
-			// If we can not lookup the account and we are a member, send this result back to the metacontroller leader.
-			result := &consumerAssignmentResult{
-				Account:  accName,
-				Stream:   stream,
-				Consumer: consumerName,
-				Response: &JSApiConsumerCreateResponse{ApiResponse: ApiResponse{Type: JSApiConsumerCreateResponseType}},
-			}
-			result.Response.Error = NewJSNoAccountError()
-			s.sendInternalMsgLocked(consumerAssignmentSubj, _EMPTY_, nil, result)
-			s.Warnf(ll)
-		} else {
-			s.Debugf(ll)
-		}
-		return
-	}
-
 	// Check if this is for us..
 	if isMember {
 		js.processClusterCreateConsumer(ca, state, wasExisting)
@@ -3522,7 +3474,6 @@ func (js *jetStream) processClusterDeleteConsumer(ca *consumerAssignment, isMemb
 	}
 	js.mu.RLock()
 	s := js.srv
-	node := ca.Group.node
 	offline := s.allPeersOffline(ca.Group)
 	var isMetaLeader bool
 	if cc := js.cluster; cc != nil {
@@ -3530,7 +3481,6 @@ func (js *jetStream) processClusterDeleteConsumer(ca *consumerAssignment, isMemb
 	}
 	js.mu.RUnlock()
 
-	stopped := false
 	var resp = JSApiConsumerDeleteResponse{ApiResponse: ApiResponse{Type: JSApiConsumerDeleteResponseType}}
 	var err error
 	var acc *Account
@@ -3540,23 +3490,13 @@ func (js *jetStream) processClusterDeleteConsumer(ca *consumerAssignment, isMemb
 		if mset, _ := acc.lookupStream(ca.Stream); mset != nil {
 			if o := mset.lookupConsumer(ca.Name); o != nil {
 				err = o.stopWithFlags(true, false, true, wasLeader)
-				stopped = true
 			}
 		}
 	}
 
 	// Always delete the node if present.
-	if node != nil {
-		node.Delete()
-	}
-
-	// This is a stop gap cleanup in case
-	// 1) the account does not exist (and mset consumer couldn't be stopped) and/or
-	// 2) node was nil (and couldn't be deleted)
-	if !stopped || node == nil {
-		if sacc := s.SystemAccount(); sacc != nil {
-			os.RemoveAll(filepath.Join(js.config.StoreDir, sacc.GetName(), defaultStoreDirName, ca.Group.Name))
-		}
+	if ca.Group.node != nil {
+		ca.Group.node.Delete()
 	}
 
 	if !wasLeader || ca.Reply == _EMPTY_ {
@@ -3565,11 +3505,6 @@ func (js *jetStream) processClusterDeleteConsumer(ca *consumerAssignment, isMemb
 		}
 	}
 
-	// Do not respond if the account does not exist any longer
-	if acc == nil {
-		return
-	}
-
 	if err != nil {
 		resp.Error = NewJSStreamNotFoundError(Unless(err))
 		s.sendAPIErrResponse(ca.Client, acc, ca.Subject, ca.Reply, _EMPTY_, s.jsonResponse(resp))
@@ -4245,9 +4180,7 @@ func (js *jetStream) processStreamAssignmentResults(sub *subscription, c *client
 			if cfg.Placement == nil || cfg.Placement.Cluster == _EMPTY_ {
 				// If we have additional clusters to try we can retry.
 				if ci != nil && len(ci.Alternates) > 0 {
-					if rg, err := js.createGroupForStream(ci, cfg); err != nil {
-						s.Warnf("Retrying cluster placement for stream '%s > %s' failed due to placement error: %+v", result.Account, result.Stream, err)
-					} else {
+					if rg := js.createGroupForStream(ci, cfg); rg != nil {
 						if org := sa.Group; org != nil && len(org.Peers) > 0 {
 							s.Warnf("Retrying cluster placement for stream '%s > %s' due to insufficient resources in cluster %q",
 								result.Account, result.Stream, s.clusterNameForNode(org.Peers[0]))
@@ -4344,9 +4277,6 @@ func (js *jetStream) startUpdatesSub() {
 	if cc.peerStreamCancelMove == nil {
 		cc.peerStreamCancelMove, _ = s.systemSubscribe(JSApiServerStreamCancelMove, _EMPTY_, false, c, s.jsLeaderServerStreamCancelMoveRequest)
 	}
-	if js.accountPurge == nil {
-		js.accountPurge, _ = s.systemSubscribe(JSApiAccountPurge, _EMPTY_, false, c, s.jsLeaderAccountPurgeRequest)
-	}
 }
 
 // Lock should be held.
@@ -4376,10 +4306,6 @@ func (js *jetStream) stopUpdatesSub() {
 		cc.s.sysUnsubscribe(cc.peerStreamCancelMove)
 		cc.peerStreamCancelMove = nil
 	}
-	if js.accountPurge != nil {
-		cc.s.sysUnsubscribe(js.accountPurge)
-		js.accountPurge = nil
-	}
 }
 
 func (js *jetStream) processLeaderChange(isLeader bool) {
@@ -4478,44 +4404,11 @@ func (cc *jetStreamCluster) remapStreamAssignment(sa *streamAssignment, removePe
 	return false
 }
 
-type selectPeerError struct {
-	cluster      string
-	clusterPeers int
-	offline      int
-	excludeTag   int
-	noTagMatch   int
-	noStorage    int
-	uniqueTag    int
-	misc         int
-}
-
-func (e *selectPeerError) Error() string {
-	return fmt.Sprintf(`peer selection cluster '%s' with %d peers
-offline: %d
-excludeTag: %d
-noTagMatch: %d
-noStorage: %d
-uniqueTag: %d
-misc: %d
-`,
-		e.cluster, e.clusterPeers, e.offline, e.excludeTag, e.noTagMatch, e.noStorage, e.uniqueTag, e.misc)
-}
-
-type selectPeerErrors []*selectPeerError
-
-func (e *selectPeerErrors) Error() string {
-	errors := make([]string, len(*e))
-	for i, err := range *e {
-		errors[i] = err.Error()
-	}
-	return strings.Join(errors, "\n")
-}
-
 // selectPeerGroup will select a group of peers to start a raft group.
 // when peers exist already the unique tag prefix check for the replaceFirstExisting will be skipped
-func (cc *jetStreamCluster) selectPeerGroup(r int, cluster string, cfg *StreamConfig, existing []string, replaceFirstExisting int) ([]string, *selectPeerError) {
+func (cc *jetStreamCluster) selectPeerGroup(r int, cluster string, cfg *StreamConfig, existing []string, replaceFirstExisting int) (re []string) {
 	if cluster == _EMPTY_ || cfg == nil {
-		return nil, &selectPeerError{cluster: cluster, misc: 1}
+		return nil
 	}
 
 	var maxBytes uint64
@@ -4550,28 +4443,28 @@ func (cc *jetStreamCluster) selectPeerGroup(r int, cluster string, cfg *StreamCo
 			}
 		}
 	}
-	var uniqueTags = make(map[string]*nodeInfo)
+	var uniqueTags = make(map[string]struct{})
 
-	checkUniqueTag := func(ni *nodeInfo) (bool, *nodeInfo) {
+	checkUniqueTag := func(ni *nodeInfo) bool {
+		// default requires the unique prefix to be present
+		isUnique := false
 		for _, t := range ni.tags {
 			if strings.HasPrefix(t, uniqueTagPrefix) {
-				if n, ok := uniqueTags[t]; !ok {
-					uniqueTags[t] = ni
-					return true, ni
-				} else {
-					return false, n
+				if _, ok := uniqueTags[t]; !ok {
+					uniqueTags[t] = struct{}{}
+					isUnique = true
 				}
+				break
 			}
 		}
-		// default requires the unique prefix to be present
-		return false, nil
+		return isUnique
 	}
 
 	// Map existing.
 	var ep map[string]struct{}
 	if le := len(existing); le > 0 {
 		if le >= r {
-			return existing[:r], nil
+			return existing
 		}
 		ep = make(map[string]struct{})
 		for i, p := range existing {
@@ -4591,30 +4484,17 @@ func (cc *jetStreamCluster) selectPeerGroup(r int, cluster string, cfg *StreamCo
 
 	maxHaAssets := s.getOpts().JetStreamLimits.MaxHAAssets
 
-	// An error is a result of multiple individual placement decisions.
-	// Which is why we keep taps on how often which one happened.
-	err := selectPeerError{cluster: cluster}
-
 	// Shuffle them up.
 	rand.Shuffle(len(peers), func(i, j int) { peers[i], peers[j] = peers[j], peers[i] })
 	for _, p := range peers {
 		si, ok := s.nodeToInfo.Load(p.ID)
 		if !ok || si == nil {
-			err.misc++
 			continue
 		}
 		ni := si.(nodeInfo)
 		// Only select from the designated named cluster.
-		if ni.cluster != cluster {
-			s.Debugf("Peer selection: discard %s@%s reason: not target cluster %s", ni.name, ni.cluster, cluster)
-			continue
-		}
-		err.clusterPeers++
-
-		// If we know its offline or we do not have config or err don't consider.
-		if ni.offline || ni.cfg == nil || ni.stats == nil {
-			s.Debugf("Peer selection: discard %s@%s reason: offline", ni.name, ni.cluster)
-			err.offline++
+		// If we know its offline or we do not have config or stats don't consider.
+		if ni.cluster != cluster || ni.offline || ni.cfg == nil || ni.stats == nil {
 			continue
 		}
 
@@ -4626,9 +4506,6 @@ func (cc *jetStreamCluster) selectPeerGroup(r int, cluster string, cfg *StreamCo
 		}
 
 		if ni.tags.Contains(jsExcludePlacement) {
-			s.Debugf("Peer selection: discard %s@%s tags: %v reason: %s present",
-				ni.name, ni.cluster, ni.tags, jsExcludePlacement)
-			err.excludeTag++
 			continue
 		}
 
@@ -4637,13 +4514,10 @@ func (cc *jetStreamCluster) selectPeerGroup(r int, cluster string, cfg *StreamCo
 			for _, t := range tags {
 				if !ni.tags.Contains(t) {
 					matched = false
-					s.Debugf("Peer selection: discard %s@%s tags: %v reason: mandatory tag %s not present",
-						ni.name, ni.cluster, ni.tags, t)
 					break
 				}
 			}
 			if !matched {
-				err.noTagMatch++
 				continue
 			}
 		}
@@ -4674,31 +4548,19 @@ func (cc *jetStreamCluster) selectPeerGroup(r int, cluster string, cfg *StreamCo
 
 		// Otherwise check if we have enough room if maxBytes set.
 		if maxBytes > 0 && maxBytes > available {
-			s.Warnf("Peer selection: discard %s@%s (Max Bytes: %d) exceeds available %s storage of %d bytes",
+			s.Warnf("%s@%s (Max Bytes: %d) exceeds available %s storage of %d bytes",
 				ni.name, ni.cluster, maxBytes, cfg.Storage.String(), available)
-			err.noStorage++
 			continue
 		}
 		// HAAssets contain _meta_ which we want to ignore
 		if maxHaAssets > 0 && ni.stats != nil && ni.stats.HAAssets > maxHaAssets {
-			s.Warnf("Peer selection: discard %s@%s (HA Asset Count: %d) exceeds max ha asset limit of %d for stream placement",
+			s.Warnf("%s@%s (HA Asset Count: %d) exceeds max ha asset limit of %d for stream placement",
 				ni.name, ni.cluster, ni.stats.HAAssets, maxHaAssets)
-			err.misc++
 			continue
 		}
 
-		if uniqueTagPrefix != _EMPTY_ {
-			if unique, owner := checkUniqueTag(&ni); !unique {
-				if owner != nil {
-					s.Debugf("Peer selection: discard %s@%s tags:%v reason: unique prefix %s owned by %s@%s",
-						ni.name, ni.cluster, ni.tags, owner.name, owner.cluster)
-				} else {
-					s.Debugf("Peer selection: discard %s@%s tags:%v reason: unique prefix %s not present",
-						ni.name, ni.cluster, ni.tags)
-				}
-				err.uniqueTag++
-				continue
-			}
+		if uniqueTagPrefix != _EMPTY_ && !checkUniqueTag(&ni) {
+			continue
 		}
 		// Add to our list of potential nodes.
 		nodes = append(nodes, wn{p.ID, available, ha})
@@ -4706,9 +4568,7 @@ func (cc *jetStreamCluster) selectPeerGroup(r int, cluster string, cfg *StreamCo
 
 	// If we could not select enough peers, fail.
 	if len(nodes) < (r - len(existing)) {
-		s.Debugf("Peer selection: required %d nodes but found %d (cluster: %s replica: %d existing: %v/%d peers: %d result-peers: %d err: %+v)",
-			(r - len(existing)), len(nodes), cluster, r, existing, replaceFirstExisting, len(peers), len(nodes), err)
-		return nil, &err
+		return nil
 	}
 	// Sort based on available from most to least.
 	sort.Slice(nodes, func(i, j int) bool { return nodes[i].avail > nodes[j].avail })
@@ -4726,7 +4586,7 @@ func (cc *jetStreamCluster) selectPeerGroup(r int, cluster string, cfg *StreamCo
 	for _, r := range nodes[:r] {
 		results = append(results, r.id)
 	}
-	return results, nil
+	return results
 }
 
 func groupNameForStream(peers []string, storage StorageType) string {
@@ -4773,7 +4633,7 @@ func tieredStreamAndReservationCount(asa map[string]*streamAssignment, tier stri
 
 // createGroupForStream will create a group for assignment for the stream.
 // Lock should be held.
-func (js *jetStream) createGroupForStream(ci *ClientInfo, cfg *StreamConfig) (*raftGroup, *selectPeerErrors) {
+func (js *jetStream) createGroupForStream(ci *ClientInfo, cfg *StreamConfig) *raftGroup {
 	replicas := cfg.Replicas
 	if replicas == 0 {
 		replicas = 1
@@ -4792,16 +4652,14 @@ func (js *jetStream) createGroupForStream(ci *ClientInfo, cfg *StreamConfig) (*r
 	}
 
 	// Need to create a group here.
-	errFirst := selectPeerErrors{}
 	for _, cn := range clusters {
-		peers, err := cc.selectPeerGroup(replicas, cn, cfg, nil, 0)
+		peers := cc.selectPeerGroup(replicas, cn, cfg, nil, 0)
 		if len(peers) < replicas {
-			errFirst = append(errFirst, err)
 			continue
 		}
-		return &raftGroup{Name: groupNameForStream(peers, cfg.Storage), Storage: cfg.Storage, Peers: peers, Cluster: cn}, nil
+		return &raftGroup{Name: groupNameForStream(peers, cfg.Storage), Storage: cfg.Storage, Peers: peers, Cluster: cn}
 	}
-	return nil, &errFirst
+	return nil
 }
 
 func (acc *Account) selectLimits(cfg *StreamConfig) (*JetStreamAccountLimits, string, *jsAccount, *ApiError) {
@@ -4917,9 +4775,9 @@ func (s *Server) jsClusteredStreamRequest(ci *ClientInfo, acc *Account, subject,
 	}
 
 	// Raft group selection and placement.
-	rg, err := js.createGroupForStream(ci, cfg)
-	if err != nil {
-		resp.Error = NewJSClusterNoPeersError(err)
+	rg := js.createGroupForStream(ci, cfg)
+	if rg == nil {
+		resp.Error = NewJSInsufficientResourcesError()
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -5086,9 +4944,9 @@ func (s *Server) jsClusteredStreamUpdateRequest(ci *ClientInfo, acc *Account, su
 	if isReplicaChange {
 		// We are adding new peers here.
 		if newCfg.Replicas > len(rg.Peers) {
-			peers, err := cc.selectPeerGroup(newCfg.Replicas, rg.Cluster, newCfg, rg.Peers, 0)
-			if err != nil {
-				resp.Error = NewJSClusterNoPeersError(err)
+			peers := cc.selectPeerGroup(newCfg.Replicas, rg.Cluster, newCfg, rg.Peers, 0)
+			if len(peers) != newCfg.Replicas {
+				resp.Error = NewJSInsufficientResourcesError()
 				s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 				return
 			}
@@ -5159,9 +5017,9 @@ func (s *Server) jsClusteredStreamUpdateRequest(ci *ClientInfo, acc *Account, su
 		}
 	} else if isMoveRequest {
 		if len(peerSet) == 0 {
-			nrg, err := js.createGroupForStream(ci, newCfg)
-			if err != nil {
-				resp.Error = NewJSClusterNoPeersError(err)
+			nrg := js.createGroupForStream(ci, newCfg)
+			if nrg == nil {
+				resp.Error = NewJSInsufficientResourcesError()
 				s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 				return
 			}
@@ -5345,9 +5203,9 @@ func (s *Server) jsClusteredStreamRestoreRequest(
 	}
 
 	// Raft group selection and placement.
-	rg, err := js.createGroupForStream(ci, cfg)
-	if err != nil {
-		resp.Error = NewJSClusterNoPeersError(err)
+	rg := js.createGroupForStream(ci, cfg)
+	if rg == nil {
+		resp.Error = NewJSInsufficientResourcesError()
 		s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp))
 		return
 	}
@@ -6399,11 +6257,11 @@ func (mset *stream) calculateSyncRequest(state *StreamState, snap *streamSnapsho
 func (mset *stream) processSnapshotDeletes(snap *streamSnapshot) {
 	state := mset.state()
 
-	// Always adjust if FirstSeq has moved beyond our state.
-	if snap.FirstSeq > state.FirstSeq {
+	// Adjust if FirstSeq has moved.
+	if snap.FirstSeq > state.FirstSeq && state.FirstSeq != 0 {
 		mset.store.Compact(snap.FirstSeq)
 		state = mset.store.State()
-		mset.setLastSeq(state.LastSeq)
+		mset.setLastSeq(snap.LastSeq)
 	}
 	// Range the deleted and delete if applicable.
 	for _, dseq := range snap.Deleted {
@@ -6497,14 +6355,6 @@ func (mset *stream) isCurrent() bool {
 // Maximum requests for the whole server that can be in flight.
 const maxConcurrentSyncRequests = 8
 
-var (
-	errCatchupCorruptSnapshot = errors.New("corrupt stream snapshot detected")
-	errCatchupStalled         = errors.New("catchup stalled")
-	errCatchupStreamStopped   = errors.New("stream has been stopped") // when a catchup is terminated due to the stream going away.
-	errCatchupBadMsg          = errors.New("bad catchup msg")
-	errCatchupWrongSeqForSkip = errors.New("wrong sequence for skipped msg")
-)
-
 // Process a stream snapshot.
 func (mset *stream) processSnapshot(snap *streamSnapshot) (e error) {
 	// Update any deletes, etc.
@@ -6527,7 +6377,7 @@ func (mset *stream) processSnapshot(snap *streamSnapshot) (e error) {
 
 	// Bug that would cause this to be empty on stream update.
 	if subject == _EMPTY_ {
-		return errCatchupCorruptSnapshot
+		return errors.New("corrupt stream assignment detected")
 	}
 
 	// Just return if up to date or already exceeded limits.
@@ -6540,11 +6390,15 @@ func (mset *stream) processSnapshot(snap *streamSnapshot) (e error) {
 		return err
 	}
 
+	// ErrStreamStopped is when a catchup is terminated due to the stream going away.
+	var ErrStreamStopped = errors.New("stream has been stopped")
+
 	defer func() {
-		// Don't bother resuming if server or stream is gone.
-		if e != errCatchupStreamStopped && e != ErrServerNotRunning {
-			n.ResumeApply()
+		if e == ErrServerNotRunning || e == ErrStreamStopped {
+			// Wipe our raft state if exiting with these errors.
+			n.Wipe()
 		}
+		n.ResumeApply()
 	}()
 
 	// Set our catchup state.
@@ -6554,10 +6408,24 @@ func (mset *stream) processSnapshot(snap *streamSnapshot) (e error) {
 	var sub *subscription
 	var err error
 
-	const activityInterval = 10 * time.Second
+	const maxActivityInterval = 10 * time.Second
+	const minActivityInterval = time.Second
+	activityInterval := minActivityInterval
 	notActive := time.NewTimer(activityInterval)
 	defer notActive.Stop()
 
+	var gotMsgs bool
+	getActivityInterval := func() time.Duration {
+		if gotMsgs || activityInterval == maxActivityInterval {
+			return maxActivityInterval
+		}
+		activityInterval *= 2
+		if activityInterval > maxActivityInterval {
+			activityInterval = maxActivityInterval
+		}
+		return activityInterval
+	}
+
 	defer func() {
 		if sub != nil {
 			s.sysUnsubscribe(sub)
@@ -6589,33 +6457,6 @@ func (mset *stream) processSnapshot(snap *streamSnapshot) (e error) {
 	// On exit, we will release our semaphore if we acquired it.
 	defer releaseSyncOutSem()
 
-	// Check our final state when we exit cleanly.
-	// If this snapshot was for messages no longer held by the leader we want to make sure
-	// we are synched for the next message sequence properly.
-	lastRequested := sreq.LastSeq
-	checkFinalState := func() {
-		if mset != nil {
-			mset.mu.Lock()
-			var state StreamState
-			mset.store.FastState(&state)
-			var didReset bool
-			firstExpected := lastRequested + 1
-			if state.FirstSeq != firstExpected {
-				// Reset our notion of first.
-				mset.store.Compact(firstExpected)
-				mset.store.FastState(&state)
-				// Make sure last is also correct in case this also moved.
-				mset.lseq = state.LastSeq
-				didReset = true
-			}
-			mset.mu.Unlock()
-			if didReset {
-				s.Warnf("Catchup for stream '%s > %s' resetting first sequence: %d on catchup complete",
-					mset.account(), mset.name(), firstExpected)
-			}
-		}
-	}
-
 RETRY:
 	// On retry, we need to release the semaphore we got. Call will be no-op
 	// if releaseSem boolean has not been set to true on successfully getting
@@ -6647,7 +6488,7 @@ RETRY:
 		default:
 		}
 	}
-	notActive.Reset(activityInterval)
+	notActive.Reset(getActivityInterval())
 
 	// Grab sync request again on failures.
 	if sreq == nil {
@@ -6659,8 +6500,6 @@ RETRY:
 		if sreq == nil {
 			return nil
 		}
-		// Reset notion of lastRequested
-		lastRequested = sreq.LastSeq
 	}
 
 	// Used to transfer message from the wire to another Go routine internally.
@@ -6668,14 +6507,6 @@ RETRY:
 		msg   []byte
 		reply string
 	}
-	// This is used to notify the leader that it should stop the runCatchup
-	// because we are either bailing out or going to retry due to an error.
-	notifyLeaderStopCatchup := func(mrec *im, err error) {
-		if mrec.reply == _EMPTY_ {
-			return
-		}
-		s.sendInternalMsgLocked(mrec.reply, _EMPTY_, nil, err.Error())
-	}
 
 	msgsQ := s.newIPQueue(qname) // of *im
 	defer msgsQ.unregister()
@@ -6692,11 +6523,8 @@ RETRY:
 		err = nil
 		goto RETRY
 	}
-	// Send our sync request.
 	b, _ := json.Marshal(sreq)
 	s.sendInternalMsgLocked(subject, reply, nil, b)
-	// Remember when we sent this out to avoimd loop spins on errors below.
-	reqSendTime := time.Now()
 
 	// Clear our sync request and capture last.
 	last := sreq.LastSeq
@@ -6706,10 +6534,10 @@ RETRY:
 	for qch, lch := n.QuitC(), n.LeadChangeC(); ; {
 		select {
 		case <-msgsQ.ch:
-			notActive.Reset(activityInterval)
+			gotMsgs = true
+			notActive.Reset(getActivityInterval())
 
 			mrecs := msgsQ.pop()
-
 			for _, mreci := range mrecs {
 				mrec := mreci.(*im)
 				msg := mrec.msg
@@ -6717,22 +6545,16 @@ RETRY:
 				// Check for eof signaling.
 				if len(msg) == 0 {
 					msgsQ.recycle(&mrecs)
-					checkFinalState()
 					return nil
 				}
 				if lseq, err := mset.processCatchupMsg(msg); err == nil {
-					if mrec.reply != _EMPTY_ {
-						s.sendInternalMsgLocked(mrec.reply, _EMPTY_, nil, nil)
-					}
 					if lseq >= last {
 						msgsQ.recycle(&mrecs)
 						return nil
 					}
 				} else if isOutOfSpaceErr(err) {
-					notifyLeaderStopCatchup(mrec, err)
 					return err
 				} else if err == NewJSInsufficientResourcesError() {
-					notifyLeaderStopCatchup(mrec, err)
 					if mset.js.limitsExceeded(mset.cfg.Storage) {
 						s.resourcesExeededError()
 					} else {
@@ -6741,30 +6563,17 @@ RETRY:
 					msgsQ.recycle(&mrecs)
 					return err
 				} else {
-					notifyLeaderStopCatchup(mrec, err)
 					s.Warnf("Catchup for stream '%s > %s' errored, will retry: %v", mset.account(), mset.name(), err)
 					msgsQ.recycle(&mrecs)
-
-					// Make sure we do not spin and make things worse.
-					const minRetryWait = 2 * time.Second
-					elapsed := time.Since(reqSendTime)
-					if elapsed < minRetryWait {
-						select {
-						case <-s.quitCh:
-							return ErrServerNotRunning
-						case <-qch:
-							return errCatchupStreamStopped
-						case <-time.After(minRetryWait - elapsed):
-						}
-					}
 					goto RETRY
 				}
+				if mrec.reply != _EMPTY_ {
+					s.sendInternalMsgLocked(mrec.reply, _EMPTY_, nil, nil)
+				}
 			}
 			msgsQ.recycle(&mrecs)
 		case <-notActive.C:
 			if mrecs := msgsQ.pop(); len(mrecs) > 0 {
-				mrec := mrecs[0].(*im)
-				notifyLeaderStopCatchup(mrec, errCatchupStalled)
 				msgsQ.recycle(&mrecs)
 			}
 			s.Warnf("Catchup for stream '%s > %s' stalled", mset.account(), mset.name())
@@ -6772,7 +6581,7 @@ RETRY:
 		case <-s.quitCh:
 			return ErrServerNotRunning
 		case <-qch:
-			return errCatchupStreamStopped
+			return ErrStreamStopped
 		case isLeader := <-lch:
 			if isLeader {
 				n.StepDown()
@@ -6785,12 +6594,12 @@ RETRY:
 // processCatchupMsg will be called to process out of band catchup msgs from a sync request.
 func (mset *stream) processCatchupMsg(msg []byte) (uint64, error) {
 	if len(msg) == 0 || entryOp(msg[0]) != streamMsgOp {
-		return 0, errCatchupBadMsg
+		return 0, errors.New("bad catchup msg")
 	}
 
 	subj, _, hdr, msg, seq, ts, err := decodeStreamMsg(msg[1:])
 	if err != nil {
-		return 0, errCatchupBadMsg
+		return 0, errors.New("bad catchup msg")
 	}
 
 	mset.mu.RLock()
@@ -6812,7 +6621,7 @@ func (mset *stream) processCatchupMsg(msg []byte) (uint64, error) {
 	// TODO(dlc) - formalize with skipMsgOp
 	if subj == _EMPTY_ && ts == 0 {
 		if lseq := mset.store.SkipMsg(); lseq != seq {
-			return 0, errCatchupWrongSeqForSkip
+			return 0, errors.New("wrong sequence for skipped msg")
 		}
 	} else if err := mset.store.StoreRawMsg(subj, hdr, msg, seq, ts); err != nil {
 		return 0, err
@@ -6901,34 +6710,21 @@ func (js *jetStream) clusterInfo(rg *raftGroup) *ClusterInfo {
 			if current && lastSeen > lostQuorumInterval {
 				current = false
 			}
-			// Create a peer info with common settings if the peer has not been seen
-			// yet (which can happen after the whole cluster is stopped and only some
-			// of the nodes are restarted).
-			pi := &PeerInfo{
-				Current: current,
-				Offline: true,
-				Active:  lastSeen,
-				Lag:     rp.Lag,
-				peer:    rp.ID,
-			}
-			// If node is found, complete/update the settings.
 			if sir, ok := s.nodeToInfo.Load(rp.ID); ok && sir != nil {
 				si := sir.(nodeInfo)
-				pi.Name, pi.Offline, pi.cluster = si.name, si.offline, si.cluster
-			} else {
-				// If not, then add a name that indicates that the server name
-				// is unknown at this time, and clear the lag since it is misleading
-				// (the node may not have that much lag).
-				pi.Name, pi.Lag = fmt.Sprintf("Server name unknown at this time (peerID: %s)", rp.ID), 0
+				pi := &PeerInfo{
+					Name:    si.name,
+					Current: current,
+					Offline: si.offline,
+					Active:  lastSeen,
+					Lag:     rp.Lag,
+					cluster: si.cluster,
+					peer:    rp.ID,
+				}
+				ci.Replicas = append(ci.Replicas, pi)
 			}
-			ci.Replicas = append(ci.Replicas, pi)
 		}
 	}
-	// Order the result based on the name so that we get something consistent
-	// when doing repeated stream info in the CLI, etc...
-	sort.Slice(ci.Replicas, func(i, j int) bool {
-		return ci.Replicas[i].Name < ci.Replicas[j].Name
-	})
 	return ci
 }
 
@@ -7115,18 +6911,10 @@ func (mset *stream) runCatchup(sendSubject string, sreq *streamSyncRequest) {
 
 	nextBatchC := make(chan struct{}, 1)
 	nextBatchC <- struct{}{}
-	remoteQuitCh := make(chan struct{})
 
 	// Setup ackReply for flow control.
 	ackReply := syncAckSubject()
 	ackSub, _ := s.sysSubscribe(ackReply, func(sub *subscription, c *client, _ *Account, subject, reply string, msg []byte) {
-		if len(msg) > 0 {
-			s.Warnf("Catchup for stream '%s > %s' was aborted on the remote due to: %q",
-				mset.account(), mset.name(), msg)
-			s.sysUnsubscribe(sub)
-			close(remoteQuitCh)
-			return
-		}
 		sz := ackReplySize(subject)
 		s.gcbSub(&outb, sz)
 		atomic.AddInt32(&outm, -1)
@@ -7144,62 +6932,16 @@ func (mset *stream) runCatchup(sendSubject string, sreq *streamSyncRequest) {
 	notActive := time.NewTimer(activityInterval)
 	defer notActive.Stop()
 
-	// Grab our state.
-	var state StreamState
-	mset.mu.RLock()
-	mset.store.FastState(&state)
-	mset.mu.RUnlock()
-
-	// Reset notion of first if this request wants sequences before our starting sequence
-	// and we would have nothing to send. If we have partial messages still need to send skips for those.
-	if sreq.FirstSeq < state.FirstSeq && state.FirstSeq > sreq.LastSeq {
-		s.Debugf("Catchup for stream '%s > %s' resetting request first sequence from %d to %d",
-			mset.account(), mset.name(), sreq.FirstSeq, state.FirstSeq)
-		sreq.FirstSeq = state.FirstSeq
-	}
-
 	// Setup sequences to walk through.
 	seq, last := sreq.FirstSeq, sreq.LastSeq
 	mset.setCatchupPeer(sreq.Peer, last-seq)
 	defer mset.clearCatchupPeer(sreq.Peer)
 
-	var spb int
-	sendNextBatchAndContinue := func(qch chan struct{}) bool {
+	sendNextBatchAndContinue := func() bool {
 		// Update our activity timer.
 		notActive.Reset(activityInterval)
 
-		// Check if we know we will not enter the loop because we are done.
-		if seq > last {
-			s.Noticef("Catchup for stream '%s > %s' complete", mset.account(), mset.name())
-			// EOF
-			s.sendInternalMsgLocked(sendSubject, _EMPTY_, nil, nil)
-			return false
-		}
-
-		// If we already sent a batch, we will try to make sure we process around
-		// half the FC responses - or reach a certain amount of time - before sending
-		// the next batch.
-		if spb > 0 {
-			mw := time.NewTimer(100 * time.Millisecond)
-			for done := false; !done; {
-				select {
-				case <-nextBatchC:
-					done = int(atomic.LoadInt32(&outm)) <= spb/2
-				case <-mw.C:
-					done = true
-				case <-s.quitCh:
-					return false
-				case <-qch:
-					return false
-				case <-remoteQuitCh:
-					return false
-				}
-			}
-			spb = 0
-		}
-
 		var smv StoreMsg
-
 		for ; seq <= last && atomic.LoadInt64(&outb) <= maxOutBytes && atomic.LoadInt32(&outm) <= maxOutMsgs && s.gcbTotal() <= maxTotalCatchupOutBytes; seq++ {
 			sm, err := mset.store.LoadMsg(seq, &smv)
 			// if this is not a deleted msg, bail out.
@@ -7233,25 +6975,18 @@ func (mset *stream) runCatchup(sendSubject string, sreq *streamSyncRequest) {
 				// Skip record for deleted msg.
 				em = encodeStreamMsg(_EMPTY_, _EMPTY_, nil, nil, seq, 0)
 			}
-
 			// Place size in reply subject for flow control.
 			l := int64(len(em))
 			reply := fmt.Sprintf(ackReplyT, l)
 			s.gcbAdd(&outb, l)
 			atomic.AddInt32(&outm, 1)
 			s.sendInternalMsgLocked(sendSubject, reply, nil, em)
-			spb++
 			if seq == last {
 				s.Noticef("Catchup for stream '%s > %s' complete", mset.account(), mset.name())
 				// EOF
 				s.sendInternalMsgLocked(sendSubject, _EMPTY_, nil, nil)
 				return false
 			}
-			select {
-			case <-remoteQuitCh:
-				return false
-			default:
-			}
 		}
 		return true
 	}
@@ -7275,17 +7010,15 @@ func (mset *stream) runCatchup(sendSubject string, sreq *streamSyncRequest) {
 			return
 		case <-qch:
 			return
-		case <-remoteQuitCh:
-			return
 		case <-notActive.C:
 			s.Warnf("Catchup for stream '%s > %s' stalled", mset.account(), mset.name())
 			return
 		case <-nextBatchC:
-			if !sendNextBatchAndContinue(qch) {
+			if !sendNextBatchAndContinue() {
 				return
 			}
 		case <-cbKick:
-			if !sendNextBatchAndContinue(qch) {
+			if !sendNextBatchAndContinue() {
 				return
 			}
 		}
diff --git a/server/jetstream_errors_generated.go b/server/jetstream_errors_generated.go
index ce9f62ac..c5de171f 100644
--- a/server/jetstream_errors_generated.go
+++ b/server/jetstream_errors_generated.go
@@ -14,8 +14,8 @@ const (
 	// JSClusterIncompleteErr incomplete results
 	JSClusterIncompleteErr ErrorIdentifier = 10004
 
-	// JSClusterNoPeersErrF no suitable peers for placement: {err}
-	JSClusterNoPeersErrF ErrorIdentifier = 10005
+	// JSClusterNoPeersErr no suitable peers for placement
+	JSClusterNoPeersErr ErrorIdentifier = 10005
 
 	// JSClusterNotActiveErr JetStream not in clustered mode
 	JSClusterNotActiveErr ErrorIdentifier = 10006
@@ -398,7 +398,7 @@ var (
 		JSAccountResourcesExceededErr:              {Code: 400, ErrCode: 10002, Description: "resource limits exceeded for account"},
 		JSBadRequestErr:                            {Code: 400, ErrCode: 10003, Description: "bad request"},
 		JSClusterIncompleteErr:                     {Code: 503, ErrCode: 10004, Description: "incomplete results"},
-		JSClusterNoPeersErrF:                       {Code: 400, ErrCode: 10005, Description: "no suitable peers for placement: {err}"},
+		JSClusterNoPeersErr:                        {Code: 400, ErrCode: 10005, Description: "no suitable peers for placement"},
 		JSClusterNotActiveErr:                      {Code: 500, ErrCode: 10006, Description: "JetStream not in clustered mode"},
 		JSClusterNotAssignedErr:                    {Code: 500, ErrCode: 10007, Description: "JetStream cluster not assigned to this server"},
 		JSClusterNotAvailErr:                       {Code: 503, ErrCode: 10008, Description: "JetStream system temporarily unavailable"},
@@ -579,20 +579,14 @@ func NewJSClusterIncompleteError(opts ...ErrorOption) *ApiError {
 	return ApiErrors[JSClusterIncompleteErr]
 }
 
-// NewJSClusterNoPeersError creates a new JSClusterNoPeersErrF error: "no suitable peers for placement: {err}"
-func NewJSClusterNoPeersError(err error, opts ...ErrorOption) *ApiError {
+// NewJSClusterNoPeersError creates a new JSClusterNoPeersErr error: "no suitable peers for placement"
+func NewJSClusterNoPeersError(opts ...ErrorOption) *ApiError {
 	eopts := parseOpts(opts)
 	if ae, ok := eopts.err.(*ApiError); ok {
 		return ae
 	}
 
-	e := ApiErrors[JSClusterNoPeersErrF]
-	args := e.toReplacerArgs([]interface{}{"{err}", err})
-	return &ApiError{
-		Code:        e.Code,
-		ErrCode:     e.ErrCode,
-		Description: strings.NewReplacer(args...).Replace(e.Description),
-	}
+	return ApiErrors[JSClusterNoPeersErr]
 }
 
 // NewJSClusterNotActiveError creates a new JSClusterNotActiveErr error: "JetStream not in clustered mode"
diff --git a/server/jwt.go b/server/jwt.go
index 4c97ed21..5ab89791 100644
--- a/server/jwt.go
+++ b/server/jwt.go
@@ -15,8 +15,8 @@ package server
 
 import (
 	"fmt"
+	"io/ioutil"
 	"net"
-	"os"
 	"strings"
 	"time"
 
@@ -34,7 +34,7 @@ func ReadOperatorJWT(jwtfile string) (*jwt.OperatorClaims, error) {
 }
 
 func readOperatorJWT(jwtfile string) (string, *jwt.OperatorClaims, error) {
-	contents, err := os.ReadFile(jwtfile)
+	contents, err := ioutil.ReadFile(jwtfile)
 	if err != nil {
 		// Check to see if the JWT has been inlined.
 		if !strings.HasPrefix(jwtfile, jwtPrefix) {
diff --git a/server/leafnode.go b/server/leafnode.go
index 158f000c..9cb5518a 100644
--- a/server/leafnode.go
+++ b/server/leafnode.go
@@ -20,11 +20,11 @@ import (
 	"encoding/base64"
 	"encoding/json"
 	"fmt"
+	"io/ioutil"
 	"math/rand"
 	"net"
 	"net/http"
 	"net/url"
-	"os"
 	"reflect"
 	"regexp"
 	"runtime"
@@ -142,7 +142,7 @@ func (s *Server) solicitLeafNodeRemotes(remotes []*RemoteLeafOpts) {
 		}
 		s.mu.Unlock()
 		if creds != _EMPTY_ {
-			contents, err := os.ReadFile(creds)
+			contents, err := ioutil.ReadFile(creds)
 			defer wipeSlice(contents)
 			if err != nil {
 				s.Errorf("Error reading LeafNode Remote Credentials file %q: %v", creds, err)
@@ -495,13 +495,12 @@ func (s *Server) connectToRemoteLeafNode(remote *leafNodeCfg, firstConnect bool)
 			if url != rURL.Host {
 				ipStr = fmt.Sprintf(" (%s)", url)
 			}
-			// Some test may want to disable remotes from connecting
-			if s.isLeafConnectDisabled() {
-				s.Debugf("Will not attempt to connect to remote server on %q%s, leafnodes currently disabled", rURL.Host, ipStr)
-				err = ErrLeafNodeDisabled
-			} else {
+			if s.isLeafNodeEnabled() {
 				s.Debugf("Trying to connect as leafnode to remote server on %q%s", rURL.Host, ipStr)
 				conn, err = natsDialTimeout("tcp", url, dialTimeout)
+			} else {
+				s.Debugf("Will not attempt to connect to remote server on %q%s, leafnodes currently disabled", rURL.Host, ipStr)
+				err = ErrLeafNodeDisabled
 			}
 		}
 		if err != nil {
@@ -570,10 +569,10 @@ func (s *Server) checkJetStreamMigrate(remote *leafNodeCfg) {
 }
 
 // Helper for checking.
-func (s *Server) isLeafConnectDisabled() bool {
+func (s *Server) isLeafNodeEnabled() bool {
 	s.mu.RLock()
 	defer s.mu.RUnlock()
-	return s.leafDisableConnect
+	return s.leafNodeEnabled
 }
 
 // Save off the tlsName for when we use TLS and mix hostnames and IPs. IPs usually
@@ -707,26 +706,10 @@ func (c *client) sendLeafConnect(clusterName string, tlsRequired, headers bool)
 		DenyPub:   c.leaf.remote.DenyImports,
 	}
 
-	// If a signature callback is specified, this takes precedence over anything else.
-	if cb := c.leaf.remote.SignatureCB; cb != nil {
-		nonce := c.nonce
-		c.mu.Unlock()
-		jwt, sigraw, err := cb(nonce)
-		c.mu.Lock()
-		if err == nil && c.isClosed() {
-			err = ErrConnectionClosed
-		}
-		if err != nil {
-			c.Errorf("Error signing the nonce: %v", err)
-			return err
-		}
-		sig := base64.RawURLEncoding.EncodeToString(sigraw)
-		cinfo.JWT, cinfo.Sig = jwt, sig
-
-	} else if creds := c.leaf.remote.Credentials; creds != _EMPTY_ {
-		// Check for credentials first, that will take precedence..
+	// Check for credentials first, that will take precedence..
+	if creds := c.leaf.remote.Credentials; creds != _EMPTY_ {
 		c.Debugf("Authenticating with credentials file %q", c.leaf.remote.Credentials)
-		contents, err := os.ReadFile(creds)
+		contents, err := ioutil.ReadFile(creds)
 		if err != nil {
 			c.Errorf("%v", err)
 			return err
@@ -2306,12 +2289,6 @@ func (c *client) processInboundLeafMsg(msg []byte) {
 			atomic.LoadInt64(&c.srv.gateway.totalQSubs) > 0 {
 			flag |= pmrCollectQueueNames
 		}
-		// If this is a mapped subject that means the mapped interest
-		// is what got us here, but this might not have a queue designation
-		// If that is the case, make sure we ignore to process local queue subscribers.
-		if len(c.pa.mapped) > 0 && len(c.pa.queues) == 0 {
-			flag |= pmrIgnoreEmptyQueueFilter
-		}
 		_, qnames = c.processMsgResults(acc, r, msg, nil, c.pa.subject, c.pa.reply, flag)
 	}
 
diff --git a/server/monitor.go b/server/monitor.go
index 31824c0d..9e9f6a9c 100644
--- a/server/monitor.go
+++ b/server/monitor.go
@@ -1341,7 +1341,7 @@ func (s *Server) HandleRoot(w http.ResponseWriter, r *http.Request) {
 	<a href=.%s>JetStream</a>
 	<a href=.%s>Connections</a>
 	<a href=.%s>Accounts</a>
-	<a href=.%s>Account Stats</a>
+	<a href=.%s>Account stats</a>
 	<a href=.%s>Subscriptions</a>
 	<a href=.%s>Routes</a>
 	<a href=.%s>LeafNodes</a>
@@ -2603,6 +2603,12 @@ type JSzOptions struct {
 	Limit      int    `json:"limit,omitempty"`
 }
 
+// HealthzOptions are options passed to Healthz
+type HealthzOptions struct {
+	JSEnabled    bool `json:"js-enabled,omitempty"`
+	JSServerOnly bool `json:"js-server-only,omitempty"`
+}
+
 type StreamDetail struct {
 	Name     string              `json:"name"`
 	Cluster  *ClusterInfo        `json:"cluster,omitempty"`
@@ -2928,7 +2934,19 @@ func (s *Server) HandleHealthz(w http.ResponseWriter, r *http.Request) {
 	s.httpReqStats[HealthzPath]++
 	s.mu.Unlock()
 
-	hs := s.healthz()
+	jsEnabled, err := decodeBool(w, r, "js-enabled")
+	if err != nil {
+		return
+	}
+	jsServerOnly, err := decodeBool(w, r, "js-server-only")
+	if err != nil {
+		return
+	}
+
+	hs := s.healthz(&HealthzOptions{
+		JSEnabled:    jsEnabled,
+		JSServerOnly: jsServerOnly,
+	})
 	if hs.Error != _EMPTY_ {
 		s.Warnf("Healthcheck failed: %q", hs.Error)
 		w.WriteHeader(http.StatusServiceUnavailable)
@@ -2942,9 +2960,14 @@ func (s *Server) HandleHealthz(w http.ResponseWriter, r *http.Request) {
 }
 
 // Generate health status.
-func (s *Server) healthz() *HealthStatus {
+func (s *Server) healthz(opts *HealthzOptions) *HealthStatus {
 	var health = &HealthStatus{Status: "ok"}
 
+	// set option defaults
+	if opts == nil {
+		opts = &HealthzOptions{}
+	}
+
 	if err := s.readyForConnections(time.Millisecond); err != nil {
 		health.Status = "error"
 		health.Error = err.Error()
@@ -2954,6 +2977,12 @@ func (s *Server) healthz() *HealthStatus {
 	// Check JetStream
 	js := s.getJetStream()
 	if js == nil {
+		// If JetStream should be enabled then return error status.
+		if opts.JSEnabled {
+			health.Status = "unavailable"
+			health.Error = NewJSNotEnabledError().Error()
+			return health
+		}
 		return health
 	}
 
@@ -2985,6 +3014,11 @@ func (s *Server) healthz() *HealthStatus {
 		return health
 	}
 
+	// If JSServerOnly is true, then do not check further accounts, streams and consumers.
+	if opts.JSServerOnly {
+		return health
+	}
+
 	// Range across all accounts, the streams assigned to them, and the consumers.
 	// If they are assigned to this server check their status.
 	for acc, asa := range cc.streams {
diff --git a/server/mqtt.go b/server/mqtt.go
index f4d733c0..e86558a2 100644
--- a/server/mqtt.go
+++ b/server/mqtt.go
@@ -3831,11 +3831,11 @@ func mqttFilterToNATSSubject(filter []byte) ([]byte, error) {
 // - '/' is the topic level separator.
 //
 // Conversion that occurs:
-//   - '/' is replaced with '/.' if it is the first character in mt
-//   - '/' is replaced with './' if the last or next character in mt is '/'
-//     For instance, foo//bar would become foo./.bar
-//   - '/' is replaced with '.' for all other conditions (foo/bar -> foo.bar)
-//   - '.' and ' ' cause an error to be returned.
+// - '/' is replaced with '/.' if it is the first character in mt
+// - '/' is replaced with './' if the last or next character in mt is '/'
+//   For instance, foo//bar would become foo./.bar
+// - '/' is replaced with '.' for all other conditions (foo/bar -> foo.bar)
+// - '.' and ' ' cause an error to be returned.
 //
 // If there is no need to convert anything (say "foo" remains "foo"), then
 // the no memory is allocated and the returned slice is the original `mt`.
diff --git a/server/ocsp.go b/server/ocsp.go
index fa8b2113..7511aa7b 100644
--- a/server/ocsp.go
+++ b/server/ocsp.go
@@ -21,7 +21,7 @@ import (
 	"encoding/base64"
 	"encoding/pem"
 	"fmt"
-	"io"
+	"io/ioutil"
 	"net/http"
 	"os"
 	"path/filepath"
@@ -129,7 +129,7 @@ func (oc *OCSPMonitor) getLocalStatus() ([]byte, *ocsp.Response, error) {
 	key := fmt.Sprintf("%x", sha256.Sum256(oc.Leaf.Raw))
 
 	oc.mu.Lock()
-	raw, err := os.ReadFile(filepath.Join(storeDir, defaultOCSPStoreDir, key))
+	raw, err := ioutil.ReadFile(filepath.Join(storeDir, defaultOCSPStoreDir, key))
 	oc.mu.Unlock()
 	if err != nil {
 		return nil, nil, err
@@ -168,7 +168,7 @@ func (oc *OCSPMonitor) getRemoteStatus() ([]byte, *ocsp.Response, error) {
 			return nil, fmt.Errorf("non-ok http status: %d", resp.StatusCode)
 		}
 
-		return io.ReadAll(resp.Body)
+		return ioutil.ReadAll(resp.Body)
 	}
 
 	// Request documentation:
@@ -734,7 +734,7 @@ func hasOCSPStatusRequest(cert *x509.Certificate) bool {
 // new path, in an attempt to avoid corrupting existing data.
 func (oc *OCSPMonitor) writeOCSPStatus(storeDir, file string, data []byte) error {
 	storeDir = filepath.Join(storeDir, defaultOCSPStoreDir)
-	tmp, err := os.CreateTemp(storeDir, "tmp-cert-status")
+	tmp, err := ioutil.TempFile(storeDir, "tmp-cert-status")
 	if err != nil {
 		return err
 	}
@@ -760,7 +760,7 @@ func (oc *OCSPMonitor) writeOCSPStatus(storeDir, file string, data []byte) error
 }
 
 func parseCertPEM(name string) ([]*x509.Certificate, error) {
-	data, err := os.ReadFile(name)
+	data, err := ioutil.ReadFile(name)
 	if err != nil {
 		return nil, err
 	}
diff --git a/server/opts.go b/server/opts.go
index fe2ab2b4..0753464f 100644
--- a/server/opts.go
+++ b/server/opts.go
@@ -20,6 +20,7 @@ import (
 	"errors"
 	"flag"
 	"fmt"
+	"io/ioutil"
 	"math"
 	"net"
 	"net/url"
@@ -158,24 +159,18 @@ type LeafNodeOpts struct {
 	tlsConfigOpts *TLSConfigOpts
 }
 
-// SignatureHandler is used to sign a nonce from the server while
-// authenticating with Nkeys. The callback should sign the nonce and
-// return the JWT and the raw signature.
-type SignatureHandler func([]byte) (string, []byte, error)
-
 // RemoteLeafOpts are options for connecting to a remote server as a leaf node.
 type RemoteLeafOpts struct {
-	LocalAccount string           `json:"local_account,omitempty"`
-	NoRandomize  bool             `json:"-"`
-	URLs         []*url.URL       `json:"urls,omitempty"`
-	Credentials  string           `json:"-"`
-	SignatureCB  SignatureHandler `json:"-"`
-	TLS          bool             `json:"-"`
-	TLSConfig    *tls.Config      `json:"-"`
-	TLSTimeout   float64          `json:"tls_timeout,omitempty"`
-	Hub          bool             `json:"hub,omitempty"`
-	DenyImports  []string         `json:"-"`
-	DenyExports  []string         `json:"-"`
+	LocalAccount string      `json:"local_account,omitempty"`
+	NoRandomize  bool        `json:"-"`
+	URLs         []*url.URL  `json:"urls,omitempty"`
+	Credentials  string      `json:"-"`
+	TLS          bool        `json:"-"`
+	TLSConfig    *tls.Config `json:"-"`
+	TLSTimeout   float64     `json:"tls_timeout,omitempty"`
+	Hub          bool        `json:"hub,omitempty"`
+	DenyImports  []string    `json:"-"`
+	DenyExports  []string    `json:"-"`
 
 	// When an URL has the "ws" (or "wss") scheme, then the server will initiate the
 	// connection as a websocket connection. By default, the websocket frames will be
@@ -2986,10 +2981,10 @@ func parseAccount(v map[string]interface{}, errors, warnings *[]error) (string,
 
 // Parse an export stream or service.
 // e.g.
-// {stream: "public.>"} # No accounts means public.
-// {stream: "synadia.private.>", accounts: [cncf, natsio]}
-// {service: "pub.request"} # No accounts means public.
-// {service: "pub.special.request", accounts: [nats.io]}
+//   {stream: "public.>"} # No accounts means public.
+//   {stream: "synadia.private.>", accounts: [cncf, natsio]}
+//   {service: "pub.request"} # No accounts means public.
+//   {service: "pub.special.request", accounts: [nats.io]}
 func parseExportStreamOrService(v interface{}, errors, warnings *[]error) (*export, *export, error) {
 	var (
 		curStream  *export
@@ -3254,9 +3249,9 @@ func parseServiceLatency(root token, v interface{}) (l *serviceLatency, retErr e
 
 // Parse an import stream or service.
 // e.g.
-// {stream: {account: "synadia", subject:"public.synadia"}, prefix: "imports.synadia"}
-// {stream: {account: "synadia", subject:"synadia.private.*"}}
-// {service: {account: "synadia", subject: "pub.special.request"}, to: "synadia.request"}
+//   {stream: {account: "synadia", subject:"public.synadia"}, prefix: "imports.synadia"}
+//   {stream: {account: "synadia", subject:"synadia.private.*"}}
+//   {service: {account: "synadia", subject: "pub.special.request"}, to: "synadia.request"}
 func parseImportStreamOrService(v interface{}, errors, warnings *[]error) (*importStream, *importService, error) {
 	var (
 		curStream  *importStream
@@ -4265,7 +4260,7 @@ func GenTLSConfig(tc *TLSConfigOpts) (*tls.Config, error) {
 	}
 	// Add in CAs if applicable.
 	if tc.CaFile != "" {
-		rootPEM, err := os.ReadFile(tc.CaFile)
+		rootPEM, err := ioutil.ReadFile(tc.CaFile)
 		if err != nil || rootPEM == nil {
 			return nil, err
 		}
@@ -4975,7 +4970,7 @@ func processSignal(signal string) error {
 // 2. If such a file exists and can be read, return its contents.
 // 3. Otherwise, return the original "pidStr" string.
 func maybeReadPidFile(pidStr string) string {
-	if b, err := os.ReadFile(pidStr); err == nil {
+	if b, err := ioutil.ReadFile(pidStr); err == nil {
 		return string(b)
 	}
 	return pidStr
diff --git a/server/pse/pse_linux.go b/server/pse/pse_linux.go
index 77eb8f6a..aa986d03 100644
--- a/server/pse/pse_linux.go
+++ b/server/pse/pse_linux.go
@@ -16,6 +16,7 @@ package pse
 import (
 	"bytes"
 	"fmt"
+	"io/ioutil"
 	"os"
 	"sync/atomic"
 	"syscall"
@@ -47,7 +48,7 @@ func init() {
 
 // Sampling function to keep pcpu relevant.
 func periodic() {
-	contents, err := os.ReadFile(procStatFile)
+	contents, err := ioutil.ReadFile(procStatFile)
 	if err != nil {
 		return
 	}
@@ -87,7 +88,7 @@ func periodic() {
 
 // ProcUsage returns CPU usage
 func ProcUsage(pcpu *float64, rss, vss *int64) error {
-	contents, err := os.ReadFile(procStatFile)
+	contents, err := ioutil.ReadFile(procStatFile)
 	if err != nil {
 		return err
 	}
diff --git a/server/raft.go b/server/raft.go
index 419f580a..5ebddda6 100644
--- a/server/raft.go
+++ b/server/raft.go
@@ -20,6 +20,7 @@ import (
 	"errors"
 	"fmt"
 	"hash"
+	"io/ioutil"
 	"math"
 	"math/rand"
 	"net"
@@ -329,7 +330,7 @@ func (s *Server) bootstrapRaftNode(cfg *RaftConfig, knownPeers []string, allPeer
 	} else if stat == nil || !stat.IsDir() {
 		return fmt.Errorf("raft: storage directory is not a directory")
 	}
-	tmpfile, err := os.CreateTemp(cfg.Store, "_test_")
+	tmpfile, err := ioutil.TempFile(cfg.Store, "_test_")
 	if err != nil {
 		return fmt.Errorf("raft: storage directory is not writable")
 	}
@@ -963,7 +964,7 @@ func (n *raft) InstallSnapshot(data []byte) error {
 	sn := fmt.Sprintf(snapFileT, snap.lastTerm, snap.lastIndex)
 	sfile := filepath.Join(snapDir, sn)
 
-	if err := os.WriteFile(sfile, n.encodeSnapshot(snap), 0640); err != nil {
+	if err := ioutil.WriteFile(sfile, n.encodeSnapshot(snap), 0640); err != nil {
 		n.Unlock()
 		// We could set write err here, but if this is a temporary situation, too many open files etc.
 		// we want to retry and snapshots are not fatal.
@@ -981,7 +982,7 @@ func (n *raft) InstallSnapshot(data []byte) error {
 
 	n.Unlock()
 
-	psnaps, _ := os.ReadDir(snapDir)
+	psnaps, _ := ioutil.ReadDir(snapDir)
 	// Remove any old snapshots.
 	for _, fi := range psnaps {
 		pn := fi.Name()
@@ -1017,7 +1018,7 @@ func termAndIndexFromSnapFile(sn string) (term, index uint64, err error) {
 
 func (n *raft) setupLastSnapshot() {
 	snapDir := filepath.Join(n.sd, snapshotsDir)
-	psnaps, err := os.ReadDir(snapDir)
+	psnaps, err := ioutil.ReadDir(snapDir)
 	if err != nil {
 		return
 	}
@@ -1084,7 +1085,7 @@ func (n *raft) loadLastSnapshot() (*snapshot, error) {
 	if n.snapfile == _EMPTY_ {
 		return nil, errNoSnapAvailable
 	}
-	buf, err := os.ReadFile(n.snapfile)
+	buf, err := ioutil.ReadFile(n.snapfile)
 	if err != nil {
 		n.warn("Error reading snapshot: %v", err)
 		os.Remove(n.snapfile)
@@ -2808,7 +2809,7 @@ func (n *raft) processAppendEntry(ae *appendEntry, sub *subscription) {
 	if ae.pterm != n.pterm || ae.pindex != n.pindex {
 		// Check if this is a lower index than what we were expecting.
 		if ae.pindex < n.pindex {
-			n.debug("AppendEntry detected pindex less than ours: %d:%d vs %d:%d", ae.pterm, ae.pindex, n.pterm, n.pindex)
+			n.warn("AppendEntry detected pindex less than ours: %d:%d vs %d:%d", ae.pterm, ae.pindex, n.pterm, n.pindex)
 			var ar *appendEntryResponse
 
 			var success bool
@@ -3233,14 +3234,14 @@ func writePeerState(sd string, ps *peerState) error {
 	if _, err := os.Stat(psf); err != nil && !os.IsNotExist(err) {
 		return err
 	}
-	if err := os.WriteFile(psf, encodePeerState(ps), 0640); err != nil {
+	if err := ioutil.WriteFile(psf, encodePeerState(ps), 0640); err != nil {
 		return err
 	}
 	return nil
 }
 
 func readPeerState(sd string) (ps *peerState, err error) {
-	buf, err := os.ReadFile(filepath.Join(sd, peerStateFile))
+	buf, err := ioutil.ReadFile(filepath.Join(sd, peerStateFile))
 	if err != nil {
 		return nil, err
 	}
@@ -3253,7 +3254,7 @@ const termVoteLen = idLen + 8
 // readTermVote will read the largest term and who we voted from to stable storage.
 // Lock should be held.
 func (n *raft) readTermVote() (term uint64, voted string, err error) {
-	buf, err := os.ReadFile(filepath.Join(n.sd, termVoteFile))
+	buf, err := ioutil.ReadFile(filepath.Join(n.sd, termVoteFile))
 	if err != nil {
 		return 0, noVote, err
 	}
@@ -3316,7 +3317,7 @@ func (n *raft) fileWriter() {
 			copy(buf[0:], n.wtv)
 			n.RUnlock()
 			<-dios
-			err := os.WriteFile(tvf, buf[:], 0640)
+			err := ioutil.WriteFile(tvf, buf[:], 0640)
 			dios <- struct{}{}
 			if err != nil {
 				n.setWriteErr(err)
@@ -3327,7 +3328,7 @@ func (n *raft) fileWriter() {
 			buf := copyBytes(n.wps)
 			n.RUnlock()
 			<-dios
-			err := os.WriteFile(psf, buf, 0640)
+			err := ioutil.WriteFile(psf, buf, 0640)
 			dios <- struct{}{}
 			if err != nil {
 				n.setWriteErr(err)
diff --git a/server/route.go b/server/route.go
index e8847118..aead8697 100644
--- a/server/route.go
+++ b/server/route.go
@@ -1608,7 +1608,7 @@ func (s *Server) updateRouteSubscriptionMap(acc *Account, sub *subscription, del
 		if ls, ok := lqws[key]; ok && ls == n {
 			acc.mu.Unlock()
 			return
-		} else if n > 0 {
+		} else {
 			lqws[key] = n
 		}
 		acc.mu.Unlock()
diff --git a/server/server.go b/server/server.go
index 83525ac0..02b812c3 100644
--- a/server/server.go
+++ b/server/server.go
@@ -22,6 +22,7 @@ import (
 	"flag"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"log"
 	"math/rand"
 	"net"
@@ -163,7 +164,6 @@ type Server struct {
 	leafRemoteCfgs     []*leafNodeCfg
 	leafRemoteAccounts sync.Map
 	leafNodeEnabled    bool
-	leafDisableConnect bool // Used in test only
 
 	quitCh           chan struct{}
 	startupComplete  chan struct{}
@@ -1097,7 +1097,7 @@ func (s *Server) isRunning() bool {
 
 func (s *Server) logPid() error {
 	pidStr := strconv.Itoa(os.Getpid())
-	return os.WriteFile(s.getOpts().PidFile, []byte(pidStr), 0660)
+	return ioutil.WriteFile(s.getOpts().PidFile, []byte(pidStr), 0660)
 }
 
 // numReservedAccounts will return the number of reserved accounts configured in the server.
@@ -1625,11 +1625,6 @@ func (s *Server) Start() {
 	// Avoid RACE between Start() and Shutdown()
 	s.mu.Lock()
 	s.running = true
-	// Update leafNodeEnabled in case options have changed post NewServer()
-	// and before Start() (we should not be able to allow that, but server has
-	// direct reference to user-provided options - at least before a Reload() is
-	// performed.
-	s.leafNodeEnabled = opts.LeafNode.Port != 0 || len(opts.LeafNode.Remotes) > 0
 	s.mu.Unlock()
 
 	s.grMu.Lock()
@@ -3326,7 +3321,7 @@ func (s *Server) logPorts() {
 				s.Errorf("Error marshaling ports file: %v", err)
 				return
 			}
-			if err := os.WriteFile(portsFile, data, 0666); err != nil {
+			if err := ioutil.WriteFile(portsFile, data, 0666); err != nil {
 				s.Errorf("Error writing ports file (%s): %v", portsFile, err)
 				return
 			}
diff --git a/server/stream.go b/server/stream.go
index 1056a61b..2306782d 100644
--- a/server/stream.go
+++ b/server/stream.go
@@ -20,6 +20,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"math"
 	"math/rand"
 	"os"
@@ -60,11 +61,6 @@ type StreamConfig struct {
 	// Allow republish of the message after being sequenced and stored.
 	RePublish *RePublish `json:"republish,omitempty"`
 
-	// Allow higher performance, direct access to get individual messages. E.g. KeyValue
-	AllowDirect bool `json:"allow_direct,omitempty"`
-	// Allow higher performance and unified direct access for mirrors as well.
-	MirrorDirect bool `json:"mirror_direct,omitempty"`
-
 	// Optional qualifiers. These can not be modified after set to true.
 
 	// Sealed will seal a stream so no messages can get out or in.
@@ -76,6 +72,11 @@ type StreamConfig struct {
 	// AllowRollup allows messages to be placed into the system and purge
 	// all older messages using a special msg header.
 	AllowRollup bool `json:"allow_rollup_hdrs"`
+
+	// Allow higher performance, direct access to get individual messages. E.g. KeyValue
+	AllowDirect bool `json:"allow_direct,omitempty"`
+	// Allow higher performance and unified direct access for mirrors as well.
+	MirrorDirect bool `json:"mirror_direct,omitempty"`
 }
 
 // RePublish is for republishing messages once committed to a stream.
@@ -236,7 +237,6 @@ type stream struct {
 
 	// Direct get subscription.
 	directSub *subscription
-	lastBySub *subscription
 }
 
 type sourceInfo struct {
@@ -245,7 +245,6 @@ type sourceInfo struct {
 	cname string
 	sub   *subscription
 	dsub  *subscription
-	lbsub *subscription
 	msgs  *ipQueue // of *inMsg
 	sseq  uint64
 	dseq  uint64
@@ -795,12 +794,12 @@ func (mset *stream) setLastSeq(lseq uint64) {
 }
 
 func (mset *stream) sendCreateAdvisory() {
-	mset.mu.RLock()
+	mset.mu.Lock()
 	name := mset.cfg.Name
 	template := mset.cfg.Template
 	outq := mset.outq
 	srv := mset.srv
-	mset.mu.RUnlock()
+	mset.mu.Unlock()
 
 	if outq == nil {
 		return
@@ -1036,21 +1035,6 @@ func (s *Server) checkStreamCfg(config *StreamConfig, acc *Account) (StreamConfi
 				apiPrefixes = append(apiPrefixes, cfg.Mirror.External.ApiPrefix)
 			}
 		}
-		// Determine if we are inheriting direct gets.
-		if exists, ocfg := getStream(cfg.Mirror.Name); exists {
-			cfg.MirrorDirect = ocfg.AllowDirect
-		} else if js := s.getJetStream(); js != nil && js.isClustered() {
-			// Could not find it here. If we are clustered we can look it up.
-			js.mu.RLock()
-			if cc := js.cluster; cc != nil {
-				if as := cc.streams[acc.Name]; as != nil {
-					if sa := as[cfg.Mirror.Name]; sa != nil {
-						cfg.MirrorDirect = sa.Config.AllowDirect
-					}
-				}
-			}
-			js.mu.RUnlock()
-		}
 	}
 	if len(cfg.Sources) > 0 {
 		for _, src := range cfg.Sources {
@@ -1200,11 +1184,6 @@ func (s *Server) checkStreamCfg(config *StreamConfig, acc *Account) (StreamConfi
 		}
 	}
 
-	// Here we will auto set direct gets if MaxMsgsPerSubject is set.
-	if cfg.MaxMsgsPer > 0 {
-		cfg.AllowDirect = true
-	}
-
 	return cfg, nil
 }
 
@@ -1271,10 +1250,6 @@ func (jsa *jsAccount) configUpdateCheck(old, new *StreamConfig, s *Server) (*Str
 	if !reflect.DeepEqual(cfg.Mirror, old.Mirror) {
 		return nil, NewJSStreamMirrorNotUpdatableError()
 	}
-	// Can't change RePublish
-	if !reflect.DeepEqual(cfg.RePublish, old.RePublish) {
-		return nil, NewJSStreamInvalidConfigError(fmt.Errorf("stream configuration update can not change RePublish"))
-	}
 
 	// Do some adjustments for being sealed.
 	if cfg.Sealed {
@@ -1458,20 +1433,14 @@ func (mset *stream) updateWithAdvisory(config *StreamConfig, sendAdvisory bool)
 	}
 
 	// Check for mirror. If set but we are not a mirror just ignore for now.
-	if mset.cfg.MirrorDirect && mset.cfg.Mirror != nil {
+	if mset.cfg.MirrorDirect && mset.cfg.Mirror != nil && mset.mirror.dsub == nil {
 		if err := mset.subscribeToMirrorDirect(); err != nil {
 			// Disable since we had problems above.
 			mset.cfg.MirrorDirect = false
 		}
-	} else if !mset.cfg.MirrorDirect && mset.mirror != nil {
-		if mset.mirror.dsub != nil {
-			mset.unsubscribe(mset.mirror.dsub)
-			mset.mirror.dsub = nil
-		}
-		if mset.mirror.lbsub != nil {
-			mset.unsubscribe(mset.mirror.lbsub)
-			mset.mirror.lbsub = nil
-		}
+	} else if !mset.cfg.MirrorDirect && mset.mirror != nil && mset.mirror.dsub != nil {
+		mset.unsubscribe(mset.mirror.dsub)
+		mset.mirror.dsub = nil
 	}
 	mset.mu.Unlock()
 
@@ -2586,11 +2555,11 @@ func (m *inMsg) isControlMsg() bool {
 
 // Sends a reply to a flow control request.
 func (mset *stream) sendFlowControlReply(reply string) {
-	mset.mu.RLock()
+	mset.mu.Lock()
 	if mset.isLeader() && mset.outq != nil {
 		mset.outq.sendMsg(reply, nil)
 	}
-	mset.mu.RUnlock()
+	mset.mu.Unlock()
 }
 
 // handleFlowControl will properly handle flow control messages for both R==1 and R>1.
@@ -2941,56 +2910,31 @@ func (mset *stream) subscribeToStream() error {
 
 // Lock should be held.
 func (mset *stream) subscribeToDirect() error {
-	// We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis.
-	if mset.directSub == nil {
-		dsubj := fmt.Sprintf(JSDirectMsgGetT, mset.cfg.Name)
-		if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetRequest); err == nil {
-			mset.directSub = sub
-		} else {
-			return err
-		}
+	if mset.directSub != nil {
+		return nil
 	}
-	// Now the one that will have subject appended past stream name.
-	if mset.lastBySub == nil {
-		dsubj := fmt.Sprintf(JSDirectGetLastBySubjectT, mset.cfg.Name, fwcs)
-		// We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis.
-		if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetLastBySubjectRequest); err == nil {
-			mset.lastBySub = sub
-		} else {
-			return err
-		}
+	dsubj := fmt.Sprintf(JSDirectMsgGetT, mset.cfg.Name)
+	// We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis.
+	if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetRequest); err != nil {
+		return err
+	} else {
+		mset.directSub = sub
 	}
-
 	return nil
 }
 
 // Lock should be held.
 func (mset *stream) subscribeToMirrorDirect() error {
-	if mset.mirror == nil {
+	if mset.mirror == nil || mset.mirror.dsub != nil {
 		return nil
 	}
-
+	dsubj := fmt.Sprintf(JSDirectMsgGetT, mset.mirror.name)
 	// We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis.
-	if mset.mirror.dsub == nil {
-		dsubj := fmt.Sprintf(JSDirectMsgGetT, mset.mirror.name)
-		// We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis.
-		if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetRequest); err == nil {
-			mset.mirror.dsub = sub
-		} else {
-			return err
-		}
-	}
-	// Now the one that will have subject appended past stream name.
-	if mset.mirror.lbsub == nil {
-		dsubj := fmt.Sprintf(JSDirectGetLastBySubjectT, mset.mirror.name, fwcs)
-		// We will make this listen on a queue group by default, which can allow mirrors to participate on opt-in basis.
-		if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetLastBySubjectRequest); err == nil {
-			mset.mirror.lbsub = sub
-		} else {
-			return err
-		}
+	if sub, err := mset.queueSubscribeInternal(dsubj, dgetGroup, mset.processDirectGetRequest); err != nil {
+		return err
+	} else {
+		mset.mirror.dsub = sub
 	}
-
 	return nil
 }
 
@@ -3025,16 +2969,10 @@ func (mset *stream) unsubscribeToStream(stopping bool) error {
 		mset.stopSourceConsumers()
 	}
 
-	// In case we had a direct get subscriptions.
-	if stopping {
-		if mset.directSub != nil {
-			mset.unsubscribe(mset.directSub)
-			mset.directSub = nil
-		}
-		if mset.lastBySub != nil {
-			mset.unsubscribe(mset.lastBySub)
-			mset.lastBySub = nil
-		}
+	// In case we had a direct get subscription.
+	if mset.directSub != nil && stopping {
+		mset.unsubscribe(mset.directSub)
+		mset.directSub = nil
 	}
 
 	mset.active = false
@@ -3395,53 +3333,6 @@ func (mset *stream) processDirectGetRequest(_ *subscription, c *client, _ *Accou
 	}
 }
 
-// This is for direct get by last subject which is part of the subject itself.
-func (mset *stream) processDirectGetLastBySubjectRequest(_ *subscription, c *client, _ *Account, subject, reply string, rmsg []byte) {
-	_, msg := c.msgParts(rmsg)
-	if len(reply) == 0 {
-		return
-	}
-	// This version expects no payload.
-	if len(msg) != 0 {
-		hdr := []byte("NATS/1.0 408 Bad Request\r\n\r\n")
-		mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
-		return
-	}
-	// Extract the key.
-	var key string
-	for i, n := 0, 0; i < len(subject); i++ {
-		if subject[i] == btsep {
-			if n == 4 {
-				if start := i + 1; start < len(subject) {
-					key = subject[i+1:]
-				}
-				break
-			}
-			n++
-		}
-	}
-	if len(key) == 0 {
-		hdr := []byte("NATS/1.0 408 Bad Request\r\n\r\n")
-		mset.outq.send(newJSPubMsg(reply, _EMPTY_, _EMPTY_, hdr, nil, nil, 0))
-		return
-	}
-
-	inlineOk := c.kind != ROUTER && c.kind != GATEWAY && c.kind != LEAF
-	if !inlineOk {
-		// Check how long we have been away from the readloop for the route or gateway or leafnode.
-		// If too long move to a separate go routine.
-		if elapsed := time.Since(c.in.start); elapsed < noBlockThresh {
-			inlineOk = true
-		}
-	}
-
-	if inlineOk {
-		mset.getDirectRequest(&JSApiMsgGetRequest{LastFor: key}, reply)
-	} else {
-		go mset.getDirectRequest(&JSApiMsgGetRequest{LastFor: key}, reply)
-	}
-}
-
 // Do actual work on a direct msg request.
 // This could be called in a Go routine if we are inline for a non-client connection.
 func (mset *stream) getDirectRequest(req *JSApiMsgGetRequest, reply string) {
@@ -4197,7 +4088,6 @@ func (mset *stream) stop(deleteFlag, advisory bool) error {
 	// Remove from our account map.
 	jsa.mu.Lock()
 	delete(jsa.streams, mset.cfg.Name)
-	accName := jsa.account.Name
 	jsa.mu.Unlock()
 
 	// Clean up consumers.
@@ -4318,12 +4208,6 @@ func (mset *stream) stop(deleteFlag, advisory bool) error {
 			return err
 		}
 		js.releaseStreamResources(&mset.cfg)
-
-		// cleanup directories after the stream
-		accDir := filepath.Join(js.config.StoreDir, accName)
-		// no op if not empty
-		os.Remove(filepath.Join(accDir, streamsDir))
-		os.Remove(accDir)
 	} else if err := store.Stop(); err != nil {
 		return err
 	}
@@ -4547,7 +4431,7 @@ func (a *Account) RestoreStream(ncfg *StreamConfig, r io.Reader) (*stream, error
 			return nil, fmt.Errorf("could not create snapshots directory - %v", err)
 		}
 	}
-	sdir, err := os.MkdirTemp(sd, "snap-")
+	sdir, err := ioutil.TempDir(sd, "snap-")
 	if err != nil {
 		return nil, err
 	}
@@ -4600,7 +4484,7 @@ func (a *Account) RestoreStream(ncfg *StreamConfig, r io.Reader) (*stream, error
 	// Check metadata.
 	// The cfg passed in will be the new identity for the stream.
 	var fcfg FileStreamInfo
-	b, err := os.ReadFile(filepath.Join(sdir, JetStreamMetaFile))
+	b, err := ioutil.ReadFile(filepath.Join(sdir, JetStreamMetaFile))
 	if err != nil {
 		return nil, err
 	}
@@ -4655,7 +4539,7 @@ func (a *Account) RestoreStream(ncfg *StreamConfig, r io.Reader) (*stream, error
 
 	// Now do consumers.
 	odir := filepath.Join(ndir, consumerDir)
-	ofis, _ := os.ReadDir(odir)
+	ofis, _ := ioutil.ReadDir(odir)
 	for _, ofi := range ofis {
 		metafile := filepath.Join(odir, ofi.Name(), JetStreamMetaFile)
 		metasum := filepath.Join(odir, ofi.Name(), JetStreamMetaFileSum)
@@ -4663,7 +4547,7 @@ func (a *Account) RestoreStream(ncfg *StreamConfig, r io.Reader) (*stream, error
 			mset.stop(true, false)
 			return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err)
 		}
-		buf, err := os.ReadFile(metafile)
+		buf, err := ioutil.ReadFile(metafile)
 		if err != nil {
 			mset.stop(true, false)
 			return nil, fmt.Errorf("error restoring consumer [%q]: %v", ofi.Name(), err)
diff --git a/server/websocket.go b/server/websocket.go
index a884b49b..12400969 100644
--- a/server/websocket.go
+++ b/server/websocket.go
@@ -24,6 +24,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"log"
 	mrand "math/rand"
 	"net"
@@ -405,7 +406,7 @@ func (r *wsReadInfo) decompress() ([]byte, error) {
 		d.(flate.Resetter).Reset(r, nil)
 	}
 	// This will do the decompression.
-	b, err := io.ReadAll(d)
+	b, err := ioutil.ReadAll(d)
 	decompressorPool.Put(d)
 	// Now reset the compressed buffers list.
 	r.cbufs = nil
@@ -857,7 +858,7 @@ func wsPMCExtensionSupport(header http.Header, checkPMCOnly bool) (bool, bool) {
 	return false, false
 }
 
-// Send an HTTP error with the given `status` to the given http response writer `w`.
+// Send an HTTP error with the given `status`` to the given http response writer `w`.
 // Return an error created based on the `reason` string.
 func wsReturnHTTPError(w http.ResponseWriter, r *http.Request, status int, reason string) error {
 	err := fmt.Errorf("%s - websocket handshake error: %s", r.RemoteAddr, reason)


Test patch:
diff --git a/logger/log_test.go b/logger/log_test.go
index e289e19a..f9638892 100644
--- a/logger/log_test.go
+++ b/logger/log_test.go
@@ -17,6 +17,7 @@ import (
 	"bytes"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"log"
 	"os"
 	"path/filepath"
@@ -114,7 +115,7 @@ func TestFileLogger(t *testing.T) {
 	defer logger.Close()
 	logger.Noticef("foo")
 
-	buf, err := os.ReadFile(file.Name())
+	buf, err := ioutil.ReadFile(file.Name())
 	if err != nil {
 		t.Fatalf("Could not read logfile: %v", err)
 	}
@@ -133,7 +134,7 @@ func TestFileLogger(t *testing.T) {
 	defer logger.Close()
 	logger.Errorf("foo")
 
-	buf, err = os.ReadFile(file.Name())
+	buf, err = ioutil.ReadFile(file.Name())
 	if err != nil {
 		t.Fatalf("Could not read logfile: %v", err)
 	}
@@ -190,7 +191,7 @@ func TestFileLoggerSizeLimit(t *testing.T) {
 		logger.Noticef("This is a line in the log file")
 	}
 
-	files, err := os.ReadDir(tmpDir)
+	files, err := ioutil.ReadDir(tmpDir)
 	if err != nil {
 		t.Fatalf("Error reading logs dir: %v", err)
 	}
@@ -201,7 +202,7 @@ func TestFileLoggerSizeLimit(t *testing.T) {
 	if err := logger.Close(); err != nil {
 		t.Fatalf("Error closing log: %v", err)
 	}
-	content, err := os.ReadFile(file.Name())
+	content, err := ioutil.ReadFile(file.Name())
 	if err != nil {
 		t.Fatalf("Error loading latest log: %v", err)
 	}
@@ -223,7 +224,7 @@ func TestFileLoggerSizeLimit(t *testing.T) {
 	for i := 0; i < 50; i++ {
 		logger.Noticef("This is line %d in the log file", i+1)
 	}
-	files, err = os.ReadDir(tmpDir)
+	files, err = ioutil.ReadDir(tmpDir)
 	if err != nil {
 		t.Fatalf("Error reading logs dir: %v", err)
 	}
@@ -234,7 +235,7 @@ func TestFileLoggerSizeLimit(t *testing.T) {
 	// Now set a limit that is below current size
 	logger.SetSizeLimit(1000)
 	// Should have triggered rotation
-	files, err = os.ReadDir(tmpDir)
+	files, err = ioutil.ReadDir(tmpDir)
 	if err != nil {
 		t.Fatalf("Error reading logs dir: %v", err)
 	}
@@ -245,7 +246,7 @@ func TestFileLoggerSizeLimit(t *testing.T) {
 		t.Fatalf("Error closing log: %v", err)
 	}
 	lastBackup = files[len(files)-1]
-	content, err = os.ReadFile(file.Name())
+	content, err = ioutil.ReadFile(file.Name())
 	if err != nil {
 		t.Fatalf("Error loading latest log: %v", err)
 	}
@@ -276,12 +277,12 @@ func TestFileLoggerSizeLimit(t *testing.T) {
 	// Close
 	logger.Close()
 
-	files, err = os.ReadDir(tmpDir)
+	files, err = ioutil.ReadDir(tmpDir)
 	if err != nil {
 		t.Fatalf("Error reading logs dir: %v", err)
 	}
 	lastBackup = files[len(files)-1]
-	content, err = os.ReadFile(filepath.Join(tmpDir, lastBackup.Name()))
+	content, err = ioutil.ReadFile(filepath.Join(tmpDir, lastBackup.Name()))
 	if err != nil {
 		t.Fatalf("Error reading backup file: %v", err)
 	}
@@ -330,7 +331,7 @@ func createDir(t *testing.T, prefix string) string {
 	if err := os.MkdirAll(tempRoot, 0700); err != nil {
 		t.Fatal(err)
 	}
-	dir, err := os.MkdirTemp(tempRoot, prefix)
+	dir, err := ioutil.TempDir(tempRoot, prefix)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -339,7 +340,7 @@ func createDir(t *testing.T, prefix string) string {
 
 func createFileAtDir(t *testing.T, dir, prefix string) *os.File {
 	t.Helper()
-	f, err := os.CreateTemp(dir, prefix)
+	f, err := ioutil.TempFile(dir, prefix)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/scripts/runTestsOnTravis.sh b/scripts/runTestsOnTravis.sh
index b5497d71..ffd1cadb 100755
--- a/scripts/runTestsOnTravis.sh
+++ b/scripts/runTestsOnTravis.sh
@@ -13,7 +13,7 @@ if [ "$1" = "compile" ]; then
     $(exit $(go fmt $GO_LIST | wc -l));
     go vet $GO_LIST;
     find . -type f -name "*.go" | xargs misspell -error -locale US;
-    staticcheck -tags=js_chaos_tests $GO_LIST
+    staticcheck $GO_LIST
     if [ "$TRAVIS_TAG" != "" ]; then
         go test -race -v -run=TestVersionMatchesTag ./server -count=1 -vet=off
     fi
@@ -51,13 +51,6 @@ elif [ "$1" = "js_super_cluster_tests" ]; then
 
     go test -race -v -run=TestJetStreamSuperCluster ./server -count=1 -vet=off -timeout=30m -failfast
 
-elif [ "$1" = "js_chaos_tests" ]; then
-
-    # Run JetStream chaos tests. By convention, all JS cluster chaos
-    # tests with `TestJetStreamChaos`.
-
-    go test -race -v -p=1 -run=TestJetStreamChaos ./server -tags=js_chaos_tests -count=1 -vet=off -timeout=30m -failfast
-
 elif [ "$1" = "srv_pkg_non_js_tests" ]; then
 
     # Run all non JetStream tests in the server package. We exclude the
diff --git a/server/dirstore_test.go b/server/dirstore_test.go
index 2e7a1a6c..e5bceb57 100644
--- a/server/dirstore_test.go
+++ b/server/dirstore_test.go
@@ -17,6 +17,7 @@ import (
 	"bytes"
 	"crypto/sha256"
 	"fmt"
+	"io/ioutil"
 	"math"
 	"math/rand"
 	"os"
@@ -392,7 +393,7 @@ func createTestAccount(t *testing.T, dirStore *DirJWTStore, expSec int, accKey n
 
 func assertStoreSize(t *testing.T, dirStore *DirJWTStore, length int) {
 	t.Helper()
-	f, err := os.ReadDir(dirStore.directory)
+	f, err := ioutil.ReadDir(dirStore.directory)
 	require_NoError(t, err)
 	require_Len(t, len(f), length)
 	dirStore.Lock()
@@ -428,7 +429,7 @@ func TestExpiration(t *testing.T) {
 	failAt := time.Now().Add(4 * time.Second)
 	for time.Now().Before(failAt) {
 		time.Sleep(100 * time.Millisecond)
-		f, err := os.ReadDir(dir)
+		f, err := ioutil.ReadDir(dir)
 		require_NoError(t, err)
 		if len(f) == 1 {
 			lh := dirStore.Hash()
@@ -677,7 +678,7 @@ func TestReload(t *testing.T) {
 		jwt, err := account.Encode(accKey)
 		require_NoError(t, err)
 		file := fmt.Sprintf("%s/%s.jwt", dir, pKey)
-		err = os.WriteFile(file, []byte(jwt), 0644)
+		err = ioutil.WriteFile(file, []byte(jwt), 0644)
 		require_NoError(t, err)
 		return file
 	}
@@ -736,7 +737,7 @@ func TestExpirationUpdate(t *testing.T) {
 	h = nh
 
 	time.Sleep(1500 * time.Millisecond)
-	f, err := os.ReadDir(dir)
+	f, err := ioutil.ReadDir(dir)
 	require_NoError(t, err)
 	require_Len(t, len(f), 1)
 
@@ -746,7 +747,7 @@ func TestExpirationUpdate(t *testing.T) {
 	h = nh
 
 	time.Sleep(1500 * time.Millisecond)
-	f, err = os.ReadDir(dir)
+	f, err = ioutil.ReadDir(dir)
 	require_NoError(t, err)
 	require_Len(t, len(f), 1)
 
@@ -756,7 +757,7 @@ func TestExpirationUpdate(t *testing.T) {
 	h = nh
 
 	time.Sleep(1500 * time.Millisecond)
-	f, err = os.ReadDir(dir)
+	f, err = ioutil.ReadDir(dir)
 	require_NoError(t, err)
 	require_Len(t, len(f), 1)
 
@@ -766,7 +767,7 @@ func TestExpirationUpdate(t *testing.T) {
 	h = nh
 
 	time.Sleep(1500 * time.Millisecond)
-	f, err = os.ReadDir(dir)
+	f, err = ioutil.ReadDir(dir)
 	require_NoError(t, err)
 	require_Len(t, len(f), 0)
 
@@ -780,7 +781,7 @@ func TestTTL(t *testing.T) {
 	dir := createDir(t, "jwtstore_test")
 	require_OneJWT := func() {
 		t.Helper()
-		f, err := os.ReadDir(dir)
+		f, err := ioutil.ReadDir(dir)
 		require_NoError(t, err)
 		require_Len(t, len(f), 1)
 	}
@@ -804,7 +805,7 @@ func TestTTL(t *testing.T) {
 		// observe expiration
 		for i := 0; i < 40; i++ {
 			time.Sleep(50 * time.Millisecond)
-			f, err := os.ReadDir(dir)
+			f, err := ioutil.ReadDir(dir)
 			require_NoError(t, err)
 			if len(f) == 0 {
 				return
@@ -843,7 +844,7 @@ func TestRemove(t *testing.T) {
 			dir := createDir(t, "jwtstore_test")
 			require_OneJWT := func() {
 				t.Helper()
-				f, err := os.ReadDir(dir)
+				f, err := ioutil.ReadDir(dir)
 				require_NoError(t, err)
 				require_Len(t, len(f), 1)
 			}
diff --git a/server/events_test.go b/server/events_test.go
index 5c14f94b..0056d697 100644
--- a/server/events_test.go
+++ b/server/events_test.go
@@ -2170,6 +2170,8 @@ func TestServerEventsPingMonitorz(t *testing.T) {
 		{"JSZ", nil, &JSzOptions{}, []string{"now", "disabled"}},
 
 		{"HEALTHZ", nil, &JSzOptions{}, []string{"status"}},
+		{"HEALTHZ", &HealthzOptions{JSEnabled: true}, &JSzOptions{}, []string{"status"}},
+		{"HEALTHZ", &HealthzOptions{JSServerOnly: true}, &JSzOptions{}, []string{"status"}},
 	}
 
 	for i, test := range tests {
diff --git a/server/filestore_test.go b/server/filestore_test.go
index 5eef89a3..43b1a7fd 100644
--- a/server/filestore_test.go
+++ b/server/filestore_test.go
@@ -24,6 +24,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"math/bits"
 	"math/rand"
 	"os"
@@ -1241,7 +1242,7 @@ func TestFileStoreBitRot(t *testing.T) {
 		// Now twiddle some bits.
 		fs.mu.Lock()
 		lmb := fs.lmb
-		contents, _ := os.ReadFile(lmb.mfn)
+		contents, _ := ioutil.ReadFile(lmb.mfn)
 		var index int
 		for {
 			index = rand.Intn(len(contents))
@@ -1252,7 +1253,7 @@ func TestFileStoreBitRot(t *testing.T) {
 				break
 			}
 		}
-		os.WriteFile(lmb.mfn, contents, 0644)
+		ioutil.WriteFile(lmb.mfn, contents, 0644)
 		fs.mu.Unlock()
 
 		ld := fs.checkMsgs()
@@ -1420,7 +1421,7 @@ func TestFileStoreMeta(t *testing.T) {
 		t.Fatalf("Expected metafile's checksum %q to exist", metasum)
 	}
 
-	buf, err := os.ReadFile(metafile)
+	buf, err := ioutil.ReadFile(metafile)
 	if err != nil {
 		t.Fatalf("Error reading metafile: %v", err)
 	}
@@ -1431,7 +1432,7 @@ func TestFileStoreMeta(t *testing.T) {
 	if !reflect.DeepEqual(mconfig, mconfig2) {
 		t.Fatalf("Stream configs not equal, got %+v vs %+v", mconfig2, mconfig)
 	}
-	checksum, err := os.ReadFile(metasum)
+	checksum, err := ioutil.ReadFile(metasum)
 	if err != nil {
 		t.Fatalf("Error reading metafile checksum: %v", err)
 	}
@@ -1465,7 +1466,7 @@ func TestFileStoreMeta(t *testing.T) {
 		t.Fatalf("Expected consumer metafile's checksum %q to exist", ometasum)
 	}
 
-	buf, err = os.ReadFile(ometafile)
+	buf, err = ioutil.ReadFile(ometafile)
 	if err != nil {
 		t.Fatalf("Error reading consumer metafile: %v", err)
 	}
@@ -1477,7 +1478,7 @@ func TestFileStoreMeta(t *testing.T) {
 	if !reflect.DeepEqual(oconfig2, oconfig) {
 		t.Fatalf("Consumer configs not equal, got %+v vs %+v", oconfig2, oconfig)
 	}
-	checksum, err = os.ReadFile(ometasum)
+	checksum, err = ioutil.ReadFile(ometasum)
 
 	if err != nil {
 		t.Fatalf("Error reading consumer metafile checksum: %v", err)
@@ -1807,7 +1808,7 @@ func TestFileStoreSnapshot(t *testing.T) {
 		if err != nil {
 			t.Fatalf("Error creating snapshot")
 		}
-		snapshot, err := io.ReadAll(r.Reader)
+		snapshot, err := ioutil.ReadAll(r.Reader)
 		if err != nil {
 			t.Fatalf("Error reading snapshot")
 		}
@@ -2842,7 +2843,7 @@ func TestFileStoreStreamDeleteDirNotEmpty(t *testing.T) {
 		g := filepath.Join(storeDir, "g")
 		ready <- true
 		for i := 0; i < 100; i++ {
-			os.WriteFile(g, []byte("OK"), defaultFilePerms)
+			ioutil.WriteFile(g, []byte("OK"), defaultFilePerms)
 		}
 	}()
 
@@ -2927,7 +2928,7 @@ func TestFileStoreStreamIndexBug(t *testing.T) {
 	dir := createDir(t, "js-bad-idx-")
 	defer removeDir(t, dir)
 	fn := filepath.Join(dir, "1.idx")
-	os.WriteFile(fn, badIdxBytes, 0644)
+	ioutil.WriteFile(fn, badIdxBytes, 0644)
 	mb := &msgBlock{index: 1, ifn: fn}
 	if err := mb.readIndexInfo(); err == nil || !strings.Contains(err.Error(), "short index") {
 		t.Fatalf("Expected error during readIndexInfo(): %v", err)
diff --git a/server/jetstream_chaos_cluster_test.go b/server/jetstream_chaos_cluster_test.go
deleted file mode 100644
index 6d409d29..00000000
--- a/server/jetstream_chaos_cluster_test.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2022 The NATS Authors
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//go:build js_chaos_tests
-// +build js_chaos_tests
-
-package server
-
-import (
-	"testing"
-	"time"
-)
-
-// Bounces the entire set of nodes, then brings them back up.
-// Fail if some nodes don't come back online.
-func TestJetStreamChaosClusterBounce(t *testing.T) {
-
-	const duration = 60 * time.Second
-	const clusterSize = 3
-
-	c := createJetStreamClusterExplicit(t, "R3", clusterSize)
-	defer c.shutdown()
-
-	chaos := createClusterChaosMonkeyController(
-		t,
-		c,
-		&clusterBouncerChaosMonkey{
-			minDowntime:    0 * time.Second,
-			maxDowntime:    2 * time.Second,
-			minDownServers: clusterSize,
-			maxDownServers: clusterSize,
-			pause:          3 * time.Second,
-		},
-	)
-	chaos.start()
-	defer chaos.stop()
-
-	<-time.After(duration)
-}
-
-// Bounces a subset of the nodes, then brings them back up.
-// Fails if some nodes don't come back online.
-func TestJetStreamChaosClusterBounceSubset(t *testing.T) {
-
-	const duration = 60 * time.Second
-	const clusterSize = 3
-
-	c := createJetStreamClusterExplicit(t, "R3", clusterSize)
-	defer c.shutdown()
-
-	chaos := createClusterChaosMonkeyController(
-		t,
-		c,
-		&clusterBouncerChaosMonkey{
-			minDowntime:    0 * time.Second,
-			maxDowntime:    2 * time.Second,
-			minDownServers: 1,
-			maxDownServers: clusterSize,
-			pause:          3 * time.Second,
-		},
-	)
-	chaos.start()
-	defer chaos.stop()
-
-	<-time.After(duration)
-}
diff --git a/server/jetstream_chaos_helpers_test.go b/server/jetstream_chaos_helpers_test.go
deleted file mode 100644
index 5b3f9001..00000000
--- a/server/jetstream_chaos_helpers_test.go
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright 2022 The NATS Authors
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//go:build js_chaos_tests
-// +build js_chaos_tests
-
-package server
-
-import (
-	"fmt"
-	"math/rand"
-	"sync"
-	"testing"
-	"time"
-)
-
-// Additional cluster helpers
-
-func (c *cluster) waitOnClusterHealthz() {
-	c.t.Helper()
-	for _, cs := range c.servers {
-		c.waitOnServerHealthz(cs)
-	}
-}
-
-func (c *cluster) stopSubset(toStop []*Server) {
-	c.t.Helper()
-	for _, s := range toStop {
-		s.Shutdown()
-	}
-}
-
-func (c *cluster) selectRandomServers(numServers int) []*Server {
-	c.t.Helper()
-	if numServers > len(c.servers) {
-		panic(fmt.Sprintf("Can't select %d servers in a cluster of %d", numServers, len(c.servers)))
-	}
-	var selectedServers []*Server
-	selectedServers = append(selectedServers, c.servers...)
-	rand.Shuffle(len(selectedServers), func(x, y int) {
-		selectedServers[x], selectedServers[y] = selectedServers[y], selectedServers[x]
-	})
-	return selectedServers[0:numServers]
-}
-
-// Support functions for "chaos" testing (random injected failures)
-
-type ChaosMonkeyController interface {
-	// Launch the monkey as background routine and return
-	start()
-	// Stop a monkey that was previously started
-	stop()
-	// Run the monkey synchronously, until it is manually stopped via stopCh
-	run()
-}
-
-type ClusterChaosMonkey interface {
-	// Set defaults and validates the monkey parameters
-	validate(t *testing.T, c *cluster)
-	// Run the monkey synchronously, until it is manually stopped via stopCh
-	run(t *testing.T, c *cluster, stopCh <-chan bool)
-}
-
-// Chaos Monkey Controller that acts on a cluster
-type clusterChaosMonkeyController struct {
-	t       *testing.T
-	cluster *cluster
-	wg      sync.WaitGroup
-	stopCh  chan bool
-	ccm     ClusterChaosMonkey
-}
-
-func createClusterChaosMonkeyController(t *testing.T, c *cluster, ccm ClusterChaosMonkey) ChaosMonkeyController {
-	ccm.validate(t, c)
-	return &clusterChaosMonkeyController{
-		t:       t,
-		cluster: c,
-		stopCh:  make(chan bool, 3),
-		ccm:     ccm,
-	}
-}
-
-func (m *clusterChaosMonkeyController) start() {
-	m.t.Logf("🐵 Starting monkey")
-	m.wg.Add(1)
-	go func() {
-		defer m.wg.Done()
-		m.run()
-	}()
-}
-
-func (m *clusterChaosMonkeyController) stop() {
-	m.t.Logf("🐵 Stopping monkey")
-	m.stopCh <- true
-	m.wg.Wait()
-	m.t.Logf("🐵 Monkey stopped")
-}
-
-func (m *clusterChaosMonkeyController) run() {
-	m.ccm.run(m.t, m.cluster, m.stopCh)
-}
-
-// Cluster Chaos Monkey that selects a random subset of the nodes in a cluster (according to min/max provided),
-// shuts them down for a given duration (according to min/max provided), then brings them back up.
-// Then sleeps for a given time, and does it again until stopped.
-type clusterBouncerChaosMonkey struct {
-	minDowntime    time.Duration
-	maxDowntime    time.Duration
-	minDownServers int
-	maxDownServers int
-	pause          time.Duration
-}
-
-func (m *clusterBouncerChaosMonkey) validate(t *testing.T, c *cluster) {
-	if m.minDowntime > m.maxDowntime {
-		t.Fatalf("Min downtime %v cannot be larger than max downtime %v", m.minDowntime, m.maxDowntime)
-	}
-
-	if m.minDownServers > m.maxDownServers {
-		t.Fatalf("Min down servers %v cannot be larger than max down servers %v", m.minDownServers, m.maxDownServers)
-	}
-}
-
-func (m *clusterBouncerChaosMonkey) run(t *testing.T, c *cluster, stopCh <-chan bool) {
-	for {
-		// Pause between actions
-		select {
-		case <-stopCh:
-			return
-		case <-time.After(m.pause):
-		}
-
-		// Pick a random subset of servers
-		numServersDown := rand.Intn(1+m.maxDownServers-m.minDownServers) + m.minDownServers
-		servers := c.selectRandomServers(numServersDown)
-		serverNames := []string{}
-		for _, s := range servers {
-			serverNames = append(serverNames, s.info.Name)
-		}
-
-		// Pick a random outage interval
-		minOutageNanos := m.minDowntime.Nanoseconds()
-		maxOutageNanos := m.maxDowntime.Nanoseconds()
-		outageDurationNanos := rand.Int63n(1+maxOutageNanos-minOutageNanos) + minOutageNanos
-		outageDuration := time.Duration(outageDurationNanos)
-
-		// Take down selected servers
-		t.Logf("🐵 Taking down %d/%d servers for %v (%v)", numServersDown, len(c.servers), outageDuration, serverNames)
-		c.stopSubset(servers)
-
-		// Wait for the "outage" duration
-		select {
-		case <-stopCh:
-			return
-		case <-time.After(outageDuration):
-		}
-
-		// Restart servers and wait for cluster to be healthy
-		t.Logf("🐵 Restoring cluster")
-		c.restartAllSamePorts()
-		c.waitOnClusterHealthz()
-
-		c.waitOnClusterReady()
-		c.waitOnAllCurrent()
-		c.waitOnLeader()
-	}
-}
diff --git a/server/jetstream_cluster_test.go b/server/jetstream_cluster_test.go
index 0efdccd7..bd99bf09 100644
--- a/server/jetstream_cluster_test.go
+++ b/server/jetstream_cluster_test.go
@@ -35,8 +35,6 @@ import (
 	"testing"
 	"time"
 
-	"github.com/nats-io/jwt/v2"
-
 	"github.com/nats-io/nats.go"
 )
 
@@ -148,7 +146,7 @@ func TestJetStreamClusterStreamLimitWithAccountDefaults(t *testing.T) {
 		Replicas: 2,
 		MaxBytes: 15 * 1024 * 1024,
 	})
-	require_Contains(t, err.Error(), "no suitable peers for placement")
+	require_Error(t, err, NewJSInsufficientResourcesError(), NewJSStorageResourcesExceededError())
 }
 
 func TestJetStreamClusterSingleReplicaStreams(t *testing.T) {
@@ -1047,7 +1045,7 @@ func TestJetStreamClusterMaxBytesForStream(t *testing.T) {
 	cfg.Name = "TEST2"
 	cfg.MaxBytes *= 2
 	_, err = js.AddStream(cfg)
-	require_Contains(t, err.Error(), "no suitable peers for placement")
+	require_Error(t, err, NewJSInsufficientResourcesError(), NewJSStorageResourcesExceededError())
 }
 
 func TestJetStreamClusterStreamPublishWithActiveConsumers(t *testing.T) {
@@ -1834,18 +1832,6 @@ func TestJetStreamClusterExtendedStreamInfo(t *testing.T) {
 		t.Fatalf("Expected %d replicas, got %d", 2, len(si.Cluster.Replicas))
 	}
 
-	// Make sure that returned array is ordered
-	for i := 0; i < 50; i++ {
-		si, err := js.StreamInfo("TEST")
-		require_NoError(t, err)
-		require_True(t, len(si.Cluster.Replicas) == 2)
-		s1 := si.Cluster.Replicas[0].Name
-		s2 := si.Cluster.Replicas[1].Name
-		if s1 > s2 {
-			t.Fatalf("Expected replicas to be ordered, got %s then %s", s1, s2)
-		}
-	}
-
 	// Faster timeout since we loop below checking for condition.
 	js2, err := nc.JetStream(nats.MaxWait(250 * time.Millisecond))
 	if err != nil {
@@ -3646,8 +3632,7 @@ func TestJetStreamClusterPeerExclusionTag(t *testing.T) {
 		c.Subjects = []string{c.Name}
 		_, err := js.AddStream(&c)
 		require_Error(t, err)
-		require_Contains(t, err.Error(), "no suitable peers for placement", "3 peers",
-			"excludeTag: 1", "offline: 0", "uniqueTag: 0")
+		require_Contains(t, err.Error(), "insufficient resources")
 	}
 
 	// Test update failure
@@ -3658,8 +3643,8 @@ func TestJetStreamClusterPeerExclusionTag(t *testing.T) {
 	cfg.Replicas = 3
 	_, err = js.UpdateStream(cfg)
 	require_Error(t, err)
-	require_Contains(t, err.Error(), "no suitable peers for placement", "3 peers",
-		"excludeTag: 1", "offline: 0", "uniqueTag: 0")
+	require_Contains(t, err.Error(), "insufficient resources")
+
 	// Test tag reload removing !jetstream tag, and allowing placement again
 
 	srv := c.serverByName("S-1")
@@ -3695,309 +3680,6 @@ func TestJetStreamClusterPeerExclusionTag(t *testing.T) {
 	require_NoError(t, err)
 }
 
-func TestJetStreamClusterAccountPurge(t *testing.T) {
-	sysKp, syspub := createKey(t)
-	sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub)
-	sysCreds := newUser(t, sysKp)
-	defer removeFile(t, sysCreds)
-	accKp, accpub := createKey(t)
-	accClaim := jwt.NewAccountClaims(accpub)
-	accClaim.Limits.JetStreamLimits.DiskStorage = 1024 * 1024 * 5
-	accClaim.Limits.JetStreamLimits.MemoryStorage = 1024 * 1024 * 5
-	accJwt := encodeClaim(t, accClaim, accpub)
-	accCreds := newUser(t, accKp)
-	defer removeFile(t, accCreds)
-
-	tmlp := `
-		listen: 127.0.0.1:-1
-		server_name: %s
-		jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s'}
-		leaf {
-			listen: 127.0.0.1:-1
-		}
-		cluster {
-			name: %s
-			listen: 127.0.0.1:%d
-			routes = [%s]
-		}
-	`
-	c := createJetStreamClusterWithTemplateAndModHook(t, tmlp, "cluster", 3,
-		func(serverName, clustername, storeDir, conf string) string {
-			return conf + fmt.Sprintf(`
-				operator: %s
-				system_account: %s
-				resolver: {
-					type: full
-					dir: '%s/jwt'
-				}`, ojwt, syspub, storeDir)
-		})
-	defer c.shutdown()
-
-	c.waitOnLeader()
-
-	updateJwt(t, c.randomServer().ClientURL(), sysCreds, sysJwt, 3)
-	updateJwt(t, c.randomServer().ClientURL(), sysCreds, accJwt, 3)
-
-	createTestData := func(t *testing.T) {
-		nc := natsConnect(t, c.randomNonLeader().ClientURL(), nats.UserCredentials(accCreds))
-		defer nc.Close()
-
-		js, err := nc.JetStream()
-		require_NoError(t, err)
-		_, err = js.AddStream(&nats.StreamConfig{
-			Name:     "TEST1",
-			Subjects: []string{"foo"},
-			Replicas: 3,
-		})
-		require_NoError(t, err)
-		c.waitOnStreamLeader(accpub, "TEST1")
-
-		ci, err := js.AddConsumer("TEST1",
-			&nats.ConsumerConfig{Durable: "DUR1",
-				AckPolicy: nats.AckExplicitPolicy})
-		require_NoError(t, err)
-		require_True(t, ci.Config.Replicas == 0)
-
-		ci, err = js.AddConsumer("TEST1",
-			&nats.ConsumerConfig{Durable: "DUR2",
-				AckPolicy: nats.AckExplicitPolicy,
-				Replicas:  1})
-		require_NoError(t, err)
-		require_True(t, ci.Config.Replicas == 1)
-
-		toSend := uint64(1_000)
-		for i := uint64(0); i < toSend; i++ {
-			_, err = js.Publish("foo", nil)
-			require_NoError(t, err)
-		}
-
-		_, err = js.AddStream(&nats.StreamConfig{
-			Name:     "TEST2",
-			Subjects: []string{"bar"},
-			Replicas: 1,
-		})
-		require_NoError(t, err)
-
-		ci, err = js.AddConsumer("TEST2",
-			&nats.ConsumerConfig{Durable: "DUR1",
-				AckPolicy: nats.AckExplicitPolicy,
-				Replicas:  0})
-		require_NoError(t, err)
-		require_True(t, ci.Config.Replicas == 0)
-
-		for i := uint64(0); i < toSend; i++ {
-			_, err = js.Publish("bar", nil)
-			require_NoError(t, err)
-		}
-	}
-
-	inspectDirs := func(t *testing.T, sysTotal, accTotal int) error {
-		t.Helper()
-		sysDirs := 0
-		accDirs := 0
-		for _, s := range c.servers {
-			files, err := os.ReadDir(filepath.Join(s.getOpts().StoreDir, "jetstream", syspub, "_js_"))
-			require_NoError(t, err)
-			sysDirs += len(files) - 1 // sub 1 for _meta_
-			files, err = os.ReadDir(filepath.Join(s.getOpts().StoreDir, "jetstream", accpub, "streams"))
-			if err == nil || (err != nil && err.(*os.PathError).Error() == "no such file or directory") {
-				accDirs += len(files)
-			}
-		}
-		if sysDirs != sysTotal || accDirs != accTotal {
-			return fmt.Errorf("expected directory count does not match %d == %d, %d == %d",
-				sysDirs, sysTotal, accDirs, accTotal)
-		}
-		return nil
-	}
-
-	checkForDirs := func(t *testing.T, sysTotal, accTotal int) {
-		t.Helper()
-		checkFor(t, 20*time.Second, 250*time.Millisecond, func() error {
-			return inspectDirs(t, sysTotal, accTotal)
-		})
-	}
-
-	purge := func(t *testing.T) {
-		t.Helper()
-		ncsys, err := nats.Connect(c.randomServer().ClientURL(), nats.UserCredentials(sysCreds))
-		require_NoError(t, err)
-		defer ncsys.Close()
-
-		request := func() error {
-			var resp JSApiAccountPurgeResponse
-			m, err := ncsys.Request(fmt.Sprintf(JSApiAccountPurgeT, accpub), nil, time.Second)
-			if err != nil {
-				return err
-			}
-			if err := json.Unmarshal(m.Data, &resp); err != nil {
-				return err
-			}
-			if !resp.Initiated {
-				return fmt.Errorf("not started")
-			}
-			return nil
-		}
-		checkFor(t, 30*time.Second, 250*time.Millisecond, request)
-	}
-
-	t.Run("startup-cleanup", func(t *testing.T) {
-		_, newCleanupAcc1 := createKey(t)
-		_, newCleanupAcc2 := createKey(t)
-		for _, s := range c.servers {
-			os.MkdirAll(filepath.Join(s.getOpts().StoreDir, JetStreamStoreDir, newCleanupAcc1, streamsDir), defaultDirPerms)
-			os.MkdirAll(filepath.Join(s.getOpts().StoreDir, JetStreamStoreDir, newCleanupAcc2), defaultDirPerms)
-		}
-		createTestData(t)
-		checkForDirs(t, 6, 4)
-		c.stopAll()
-		c.restartAll()
-		for _, s := range c.servers {
-			accDir := filepath.Join(s.getOpts().StoreDir, JetStreamStoreDir, newCleanupAcc1)
-			_, e := os.Stat(filepath.Join(accDir, streamsDir))
-			require_Error(t, e)
-			require_True(t, os.IsNotExist(e))
-			_, e = os.Stat(accDir)
-			require_Error(t, e)
-			require_True(t, os.IsNotExist(e))
-			_, e = os.Stat(filepath.Join(s.getOpts().StoreDir, JetStreamStoreDir, newCleanupAcc2))
-			require_Error(t, e)
-			require_True(t, os.IsNotExist(e))
-		}
-		checkForDirs(t, 6, 4)
-	})
-
-	t.Run("purge-with-restart", func(t *testing.T) {
-		createTestData(t)
-		checkForDirs(t, 6, 4)
-		purge(t)
-		checkForDirs(t, 0, 0)
-		c.stopAll()
-		c.restartAll()
-		checkForDirs(t, 0, 0)
-	})
-
-	t.Run("purge-with-reuse", func(t *testing.T) {
-		createTestData(t)
-		checkForDirs(t, 6, 4)
-		purge(t)
-		checkForDirs(t, 0, 0)
-		createTestData(t)
-		checkForDirs(t, 6, 4)
-		purge(t)
-		checkForDirs(t, 0, 0)
-	})
-
-	t.Run("purge-deleted-account", func(t *testing.T) {
-		createTestData(t)
-		checkForDirs(t, 6, 4)
-		c.stopAll()
-		for _, s := range c.servers {
-			require_NoError(t, os.Remove(s.getOpts().StoreDir+"/jwt/"+accpub+".jwt"))
-		}
-		c.restartAll()
-		checkForDirs(t, 6, 4)
-		c.waitOnClusterReady() // unfortunately, this does not wait until leader is not catching up.
-		purge(t)
-		checkForDirs(t, 0, 0)
-		c.stopAll()
-		c.restartAll()
-		checkForDirs(t, 0, 0)
-	})
-}
-
-func TestJetStreamAccountPurge(t *testing.T) {
-	sysKp, syspub := createKey(t)
-	sysJwt := encodeClaim(t, jwt.NewAccountClaims(syspub), syspub)
-	sysCreds := newUser(t, sysKp)
-	defer removeFile(t, sysCreds)
-	accKp, accpub := createKey(t)
-	accClaim := jwt.NewAccountClaims(accpub)
-	accClaim.Limits.JetStreamLimits.DiskStorage = 1024 * 1024 * 5
-	accClaim.Limits.JetStreamLimits.MemoryStorage = 1024 * 1024 * 5
-	accJwt := encodeClaim(t, accClaim, accpub)
-	accCreds := newUser(t, accKp)
-	defer removeFile(t, accCreds)
-
-	storeDir := createDir(t, _EMPTY_)
-	defer os.RemoveAll(storeDir)
-
-	cfg := createConfFile(t, []byte(fmt.Sprintf(`
-        host: 127.0.0.1
-        port:-1
-        server_name: S1
-        operator: %s
-        system_account: %s
-        resolver: {
-                type: full
-                dir: '%s/jwt'
-        }
-        jetstream: {max_mem_store: 256MB, max_file_store: 2GB, store_dir: '%s/js'}
-`, ojwt, syspub, storeDir, storeDir)))
-	defer os.Remove(cfg)
-
-	s, o := RunServerWithConfig(cfg)
-	updateJwt(t, s.ClientURL(), sysCreds, sysJwt, 1)
-	updateJwt(t, s.ClientURL(), sysCreds, accJwt, 1)
-	defer s.Shutdown()
-
-	inspectDirs := func(t *testing.T, accTotal int) error {
-		t.Helper()
-		if accTotal == 0 {
-			files, err := os.ReadDir(filepath.Join(o.StoreDir, "jetstream", accpub))
-			require_True(t, len(files) == accTotal || err != nil)
-		} else {
-			files, err := os.ReadDir(filepath.Join(o.StoreDir, "jetstream", accpub, "streams"))
-			require_NoError(t, err)
-			require_True(t, len(files) == accTotal)
-		}
-		return nil
-	}
-
-	createTestData := func() {
-		nc := natsConnect(t, s.ClientURL(), nats.UserCredentials(accCreds))
-		defer nc.Close()
-		js, err := nc.JetStream()
-		require_NoError(t, err)
-		_, err = js.AddStream(&nats.StreamConfig{
-			Name:     "TEST1",
-			Subjects: []string{"foo"},
-		})
-		require_NoError(t, err)
-		_, err = js.AddConsumer("TEST1",
-			&nats.ConsumerConfig{Durable: "DUR1",
-				AckPolicy: nats.AckExplicitPolicy})
-		require_NoError(t, err)
-	}
-
-	purge := func(t *testing.T) {
-		t.Helper()
-		var resp JSApiAccountPurgeResponse
-		ncsys := natsConnect(t, s.ClientURL(), nats.UserCredentials(sysCreds))
-		defer ncsys.Close()
-		m, err := ncsys.Request(fmt.Sprintf(JSApiAccountPurgeT, accpub), nil, 5*time.Second)
-		require_NoError(t, err)
-		err = json.Unmarshal(m.Data, &resp)
-		require_NoError(t, err)
-		require_True(t, resp.Initiated)
-	}
-
-	createTestData()
-	inspectDirs(t, 1)
-	purge(t)
-	inspectDirs(t, 0)
-	createTestData()
-	inspectDirs(t, 1)
-
-	s.Shutdown()
-	require_NoError(t, os.Remove(storeDir+"/jwt/"+accpub+".jwt"))
-
-	s, o = RunServerWithConfig(o.ConfigFile)
-	inspectDirs(t, 1)
-	purge(t)
-	inspectDirs(t, 0)
-}
-
 func TestJetStreamClusterScaleConsumer(t *testing.T) {
 	c := createJetStreamClusterWithTemplate(t, jsClusterTempl, "C", 3)
 	defer c.shutdown()
@@ -5091,6 +4773,83 @@ func TestJetStreamClusterStreamDirectGetMsg(t *testing.T) {
 	require_True(t, m.Header.Get(JSTimeStamp) != _EMPTY_)
 }
 
+func TestJetStreamClusterStreamAndMirrorDirectGetMsgUpdate(t *testing.T) {
+	c := createJetStreamClusterExplicit(t, "R3F", 3)
+	defer c.shutdown()
+
+	// Client based API
+	s := c.randomServer()
+	nc, _ := jsClientConnect(t, s)
+	defer nc.Close()
+
+	cfg := &StreamConfig{
+		Name:     "TEST",
+		Subjects: []string{"foo"},
+		Storage:  MemoryStorage,
+		Replicas: 3,
+	}
+	addStream(t, nc, cfg)
+	sendStreamMsg(t, nc, "foo", "bar")
+
+	getSubj := fmt.Sprintf(JSDirectMsgGetT, "TEST")
+	req := []byte(`{"last_by_subj": "foo"}`)
+
+	_, err := nc.Request(getSubj, req, 50*time.Millisecond)
+	require_Error(t, err, nats.ErrTimeout)
+
+	cfg.AllowDirect = true
+	jreq, err := json.Marshal(cfg)
+	require_NoError(t, err)
+
+	resp, err := nc.Request(fmt.Sprintf(JSApiStreamUpdateT, "TEST"), jreq, time.Second)
+	require_NoError(t, err)
+	var scResp JSApiStreamCreateResponse
+	err = json.Unmarshal(resp.Data, &scResp)
+	require_NoError(t, err)
+	require_True(t, scResp.Error == nil)
+
+	_, err = nc.Request(getSubj, req, 50*time.Millisecond)
+	require_NoError(t, err)
+
+	// Make sure we can turn it off as well.
+	cfg.AllowDirect = false
+	jreq, err = json.Marshal(cfg)
+	require_NoError(t, err)
+
+	resp, err = nc.Request(fmt.Sprintf(JSApiStreamUpdateT, "TEST"), jreq, time.Second)
+	require_NoError(t, err)
+	err = json.Unmarshal(resp.Data, &scResp)
+	require_NoError(t, err)
+	require_True(t, scResp.Error == nil)
+
+	_, err = nc.Request(getSubj, req, 50*time.Millisecond)
+	require_Error(t, err, nats.ErrTimeout)
+
+	// Now test mirrors as well.
+	cfg = &StreamConfig{
+		Name:    "M",
+		Mirror:  &StreamSource{Name: "TEST"},
+		Storage: MemoryStorage,
+	}
+	addStream(t, nc, cfg)
+
+	_, err = nc.Request(getSubj, req, 50*time.Millisecond)
+	require_Error(t, err, nats.ErrTimeout)
+
+	cfg.MirrorDirect = true
+	jreq, err = json.Marshal(cfg)
+	require_NoError(t, err)
+
+	resp, err = nc.Request(fmt.Sprintf(JSApiStreamUpdateT, "M"), jreq, time.Second)
+	require_NoError(t, err)
+	err = json.Unmarshal(resp.Data, &scResp)
+	require_NoError(t, err)
+	require_True(t, scResp.Error == nil)
+
+	_, err = nc.Request(getSubj, req, 50*time.Millisecond)
+	require_NoError(t, err)
+}
+
 func TestJetStreamClusterStreamPerf(t *testing.T) {
 	// Comment out to run, holding place for now.
 	skip(t)
@@ -8859,7 +8618,7 @@ func TestJetStreamClusterStreamUpdateSyncBug(t *testing.T) {
 		t.Fatalf("Unexpected error: %v", err)
 	}
 
-	// Shutdown a server. The bug is that the update wiped the sync subject used to catchup a stream that has the RAFT layer snapshotted.
+	// Shutdown a server. The bug is that the update wiped the sync subject used to cacthup a stream that has the RAFT layer snapshotted.
 	nsl := c.randomNonStreamLeader("$G", "TEST")
 	nsl.Shutdown()
 	// make sure a leader exists
@@ -9411,7 +9170,7 @@ func TestJetStreamClusterBalancedPlacement(t *testing.T) {
 		Replicas: 2,
 		MaxBytes: 1 * 1024 * 1024 * 1024,
 	})
-	require_Contains(t, err.Error(), "no suitable peers for placement")
+	require_Error(t, err, NewJSInsufficientResourcesError(), NewJSStorageResourcesExceededError())
 }
 
 func TestJetStreamClusterConsumerPendingBug(t *testing.T) {
@@ -10859,7 +10618,7 @@ func TestJetStreamClusterMemoryConsumerInterestRetention(t *testing.T) {
 
 	nsi, err := js.StreamInfo("test")
 	require_NoError(t, err)
-	if !reflect.DeepEqual(nsi.State, si.State) {
+	if nsi.State != si.State {
 		t.Fatalf("Stream states do not match: %+v vs %+v", si.State, nsi.State)
 	}
 
@@ -11949,569 +11708,3 @@ func TestJetStreamClusterEncryptedDoubleSnapshotBug(t *testing.T) {
 	_, err = js.Publish("foo", []byte("SNAP3"))
 	require_NoError(t, err)
 }
-
-func TestJetStreamClusterRePublishUpdateNotSupported(t *testing.T) {
-	test := func(t *testing.T, s *Server, stream string, replicas int) {
-		nc := natsConnect(t, s.ClientURL())
-		defer nc.Close()
-
-		cfg := &StreamConfig{
-			Name:     stream,
-			Storage:  MemoryStorage,
-			Replicas: replicas,
-		}
-		addStream(t, nc, cfg)
-
-		cfg.RePublish = &RePublish{
-			Source:      ">",
-			Destination: "bar.>",
-		}
-		// We expect update to fail, do it manually:
-		expectFailUpdate := func() {
-			t.Helper()
-
-			req, err := json.Marshal(cfg)
-			require_NoError(t, err)
-			rmsg, err := nc.Request(fmt.Sprintf(JSApiStreamUpdateT, cfg.Name), req, time.Second)
-			require_NoError(t, err)
-			var resp JSApiStreamCreateResponse
-			err = json.Unmarshal(rmsg.Data, &resp)
-			require_NoError(t, err)
-			if resp.Type != JSApiStreamUpdateResponseType {
-				t.Fatalf("Invalid response type %s expected %s", resp.Type, JSApiStreamUpdateResponseType)
-			}
-			if !IsNatsErr(resp.Error, JSStreamInvalidConfigF) {
-				t.Fatalf("Expected error regarding config error, got %+v", resp.Error)
-			}
-		}
-		expectFailUpdate()
-
-		// Now try with a new stream with RePublish present and then try to change config
-		cfg = &StreamConfig{
-			Name:     stream + "_2",
-			Storage:  MemoryStorage,
-			Replicas: replicas,
-			RePublish: &RePublish{
-				Source:      ">",
-				Destination: "bar.>",
-			},
-		}
-		addStream(t, nc, cfg)
-		cfg.RePublish.HeadersOnly = true
-		expectFailUpdate()
-
-		// One last test with existing first, then trying to remove
-		cfg.Name = stream + "_3"
-		addStream(t, nc, cfg)
-		cfg.RePublish = nil
-		expectFailUpdate()
-	}
-
-	s := RunBasicJetStreamServer()
-	if config := s.JetStreamConfig(); config != nil {
-		defer removeDir(t, config.StoreDir)
-	}
-	defer s.Shutdown()
-
-	c := createJetStreamClusterExplicit(t, "JSC", 3)
-	defer c.shutdown()
-
-	t.Run("Single", func(t *testing.T) { test(t, s, "single", 1) })
-	t.Run("Clustered", func(t *testing.T) { test(t, c.randomServer(), "clustered", 3) })
-}
-
-func TestJetStreamClusterDirectGetFromLeafnode(t *testing.T) {
-	tmpl := strings.Replace(jsClusterAccountsTempl, "store_dir:", "domain: CORE, store_dir:", 1)
-	c := createJetStreamCluster(t, tmpl, "CORE", _EMPTY_, 3, 19022, true)
-	defer c.shutdown()
-
-	tmpl = strings.Replace(jsClusterTemplWithSingleLeafNode, "store_dir:", "domain: SPOKE, store_dir:", 1)
-	ln := c.createLeafNodeWithTemplate("LN-SPOKE", tmpl)
-	defer ln.Shutdown()
-
-	checkLeafNodeConnectedCount(t, ln, 2)
-
-	nc, js := jsClientConnect(t, c.randomServer())
-	defer nc.Close()
-
-	kv, err := js.CreateKeyValue(&nats.KeyValueConfig{Bucket: "KV"})
-	require_NoError(t, err)
-
-	_, err = kv.PutString("age", "22")
-	require_NoError(t, err)
-
-	// Now connect to the ln and make sure we can do a domain direct get.
-	nc, _ = jsClientConnect(t, ln)
-	defer nc.Close()
-
-	js, err = nc.JetStream(nats.Domain("CORE"))
-	require_NoError(t, err)
-
-	kv, err = js.KeyValue("KV")
-	require_NoError(t, err)
-
-	entry, err := kv.Get("age")
-	require_NoError(t, err)
-	require_True(t, string(entry.Value()) == "22")
-}
-
-func TestJetStreamClusterUnknownReplicaOnClusterRestart(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "JSC", 3)
-	defer c.shutdown()
-
-	nc, js := jsClientConnect(t, c.randomServer())
-	defer nc.Close()
-
-	_, err := js.AddStream(&nats.StreamConfig{Name: "TEST", Subjects: []string{"foo"}, Replicas: 3})
-	require_NoError(t, err)
-
-	c.waitOnStreamLeader(globalAccountName, "TEST")
-	lname := c.streamLeader(globalAccountName, "TEST").Name()
-	sendStreamMsg(t, nc, "foo", "msg1")
-
-	nc.Close()
-	c.stopAll()
-	// Restart the leader...
-	for _, s := range c.servers {
-		if s.Name() == lname {
-			c.restartServer(s)
-		}
-	}
-	// And one of the other servers
-	for _, s := range c.servers {
-		if s.Name() != lname {
-			c.restartServer(s)
-			break
-		}
-	}
-	c.waitOnStreamLeader(globalAccountName, "TEST")
-
-	nc, js = jsClientConnect(t, c.randomServer())
-	defer nc.Close()
-	sendStreamMsg(t, nc, "foo", "msg2")
-
-	si, err := js.StreamInfo("TEST")
-	require_NoError(t, err)
-	if len(si.Cluster.Replicas) != 2 {
-		t.Fatalf("Leader is %s - expected 2 peers, got %+v", si.Cluster.Leader, si.Cluster.Replicas[0])
-	}
-	// However, since the leader does not know the name of the server
-	// we should report an "unknown" name.
-	var ok bool
-	for _, r := range si.Cluster.Replicas {
-		if strings.Contains(r.Name, "unknown") {
-			// Check that it has no lag reported, and the it is not current.
-			if r.Current {
-				t.Fatal("Expected non started node to be marked as not current")
-			}
-			if r.Lag != 0 {
-				t.Fatalf("Expected lag to not be set, was %v", r.Lag)
-			}
-			if r.Active != 0 {
-				t.Fatalf("Expected active to not be set, was: %v", r.Active)
-			}
-			ok = true
-			break
-		}
-	}
-	if !ok {
-		t.Fatalf("Should have had an unknown server name, did not: %+v - %+v", si.Cluster.Replicas[0], si.Cluster.Replicas[1])
-	}
-}
-
-func TestJetStreamClusterSnapshotBeforePurgeAndCatchup(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "JSC", 3)
-	defer c.shutdown()
-
-	nc, js := jsClientConnect(t, c.randomServer())
-	defer nc.Close()
-
-	_, err := js.AddStream(&nats.StreamConfig{
-		Name:     "TEST",
-		Subjects: []string{"foo"},
-		MaxAge:   5 * time.Second,
-		Replicas: 3,
-	})
-	require_NoError(t, err)
-
-	sl := c.streamLeader("$G", "TEST")
-	nl := c.randomNonStreamLeader("$G", "TEST")
-
-	// Make sure we do not get disconnected when shutting the non-leader down.
-	nc, js = jsClientConnect(t, sl)
-	defer nc.Close()
-
-	send1k := func() {
-		t.Helper()
-		for i := 0; i < 1000; i++ {
-			js.PublishAsync("foo", []byte("SNAP"))
-		}
-		select {
-		case <-js.PublishAsyncComplete():
-		case <-time.After(5 * time.Second):
-			t.Fatalf("Did not receive completion signal")
-		}
-	}
-
-	// Send first 100 to everyone.
-	send1k()
-
-	// Now shutdown a non-leader.
-	c.waitOnStreamCurrent(nl, "$G", "TEST")
-	nl.Shutdown()
-
-	// Send another 100.
-	send1k()
-
-	// Force snapshot on the leader.
-	mset, err := sl.GlobalAccount().lookupStream("TEST")
-	require_NoError(t, err)
-	err = mset.raftNode().InstallSnapshot(mset.stateSnapshot())
-	require_NoError(t, err)
-
-	// Purge
-	err = js.PurgeStream("TEST")
-	require_NoError(t, err)
-
-	// Send another 100.
-	send1k()
-
-	// We want to make sure we do not send unnecessary skip msgs when we know we do not have all of these messages.
-	nc, _ = jsClientConnect(t, sl, nats.UserInfo("admin", "s3cr3t!"))
-	defer nc.Close()
-	sub, err := nc.SubscribeSync("$JSC.R.>")
-	require_NoError(t, err)
-
-	// Now restart non-leader.
-	nl = c.restartServer(nl)
-	c.waitOnStreamCurrent(nl, "$G", "TEST")
-
-	// Grab state directly from non-leader.
-	mset, err = nl.GlobalAccount().lookupStream("TEST")
-	require_NoError(t, err)
-
-	if state := mset.state(); state.FirstSeq != 2001 || state.LastSeq != 3000 {
-		t.Fatalf("Incorrect state: %+v", state)
-	}
-
-	// Make sure we only sent 1 sync catchup msg.
-	nmsgs, _, _ := sub.Pending()
-	if nmsgs != 1 {
-		t.Fatalf("Expected only 1 sync catchup msg to be sent signaling eof, but got %d", nmsgs)
-	}
-}
-
-func TestJetStreamClusterStreamResetWithLargeFirstSeq(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "JSC", 3)
-	defer c.shutdown()
-
-	nc, js := jsClientConnect(t, c.randomServer())
-	defer nc.Close()
-
-	cfg := &nats.StreamConfig{
-		Name:     "TEST",
-		Subjects: []string{"foo"},
-		MaxAge:   5 * time.Second,
-		Replicas: 1,
-	}
-	_, err := js.AddStream(cfg)
-	require_NoError(t, err)
-
-	// Fake a very large first seq.
-	sl := c.streamLeader("$G", "TEST")
-	mset, err := sl.GlobalAccount().lookupStream("TEST")
-	require_NoError(t, err)
-
-	mset.mu.Lock()
-	mset.store.Compact(1_000_000)
-	mset.mu.Unlock()
-	// Restart
-	sl.Shutdown()
-	sl = c.restartServer(sl)
-	c.waitOnStreamLeader("$G", "TEST")
-
-	nc, js = jsClientConnect(t, c.randomServer())
-	defer nc.Close()
-
-	// Make sure we have the correct state after restart.
-	si, err := js.StreamInfo("TEST")
-	require_NoError(t, err)
-	require_True(t, si.State.FirstSeq == 1_000_000)
-
-	// Now add in 10,000 messages.
-	num := 10_000
-	for i := 0; i < num; i++ {
-		js.PublishAsync("foo", []byte("SNAP"))
-	}
-	select {
-	case <-js.PublishAsyncComplete():
-	case <-time.After(5 * time.Second):
-		t.Fatalf("Did not receive completion signal")
-	}
-
-	si, err = js.StreamInfo("TEST")
-	require_NoError(t, err)
-	require_True(t, si.State.FirstSeq == 1_000_000)
-	require_True(t, si.State.LastSeq == uint64(1_000_000+num-1))
-
-	// We want to make sure we do not send unnecessary skip msgs when we know we do not have all of these messages.
-	ncs, _ := jsClientConnect(t, sl, nats.UserInfo("admin", "s3cr3t!"))
-	defer nc.Close()
-	sub, err := ncs.SubscribeSync("$JSC.R.>")
-	require_NoError(t, err)
-
-	// Now scale up to R3.
-	cfg.Replicas = 3
-	_, err = js.UpdateStream(cfg)
-	require_NoError(t, err)
-	nl := c.randomNonStreamLeader("$G", "TEST")
-	c.waitOnStreamCurrent(nl, "$G", "TEST")
-
-	// Make sure we only sent the number of catchup msgs we expected.
-	checkFor(t, 5*time.Second, 50*time.Millisecond, func() error {
-		if nmsgs, _, _ := sub.Pending(); nmsgs != (cfg.Replicas-1)*(num+1) {
-			return fmt.Errorf("expected %d catchup msgs, but got %d", (cfg.Replicas-1)*(num+1), nmsgs)
-		}
-		return nil
-	})
-}
-
-func TestJetStreamClusterStreamCatchupInteriorNilMsgs(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "JSC", 3)
-	defer c.shutdown()
-
-	nc, js := jsClientConnect(t, c.randomServer())
-	defer nc.Close()
-
-	cfg := &nats.StreamConfig{
-		Name:     "TEST",
-		Subjects: []string{"foo"},
-	}
-	_, err := js.AddStream(cfg)
-	require_NoError(t, err)
-
-	num := 100
-	for l := 0; l < 5; l++ {
-		for i := 0; i < num-1; i++ {
-			js.PublishAsync("foo", []byte("SNAP"))
-		}
-		// Blank msg.
-		js.PublishAsync("foo", nil)
-	}
-	select {
-	case <-js.PublishAsyncComplete():
-	case <-time.After(5 * time.Second):
-		t.Fatalf("Did not receive completion signal")
-	}
-
-	// Make sure we have the correct state after restart.
-	si, err := js.StreamInfo("TEST")
-	require_NoError(t, err)
-	require_True(t, si.State.Msgs == 500)
-
-	// Now scale up to R3.
-	cfg.Replicas = 3
-	_, err = js.UpdateStream(cfg)
-	require_NoError(t, err)
-	nl := c.randomNonStreamLeader("$G", "TEST")
-	c.waitOnStreamCurrent(nl, "$G", "TEST")
-
-	mset, err := nl.GlobalAccount().lookupStream("TEST")
-	require_NoError(t, err)
-
-	mset.mu.RLock()
-	state := mset.store.State()
-	mset.mu.RUnlock()
-	require_True(t, state.Msgs == 500)
-}
-
-type captureCatchupWarnLogger struct {
-	DummyLogger
-	ch chan string
-}
-
-func (l *captureCatchupWarnLogger) Warnf(format string, args ...interface{}) {
-	msg := fmt.Sprintf(format, args...)
-	if strings.Contains(msg, "simulate error") {
-		select {
-		case l.ch <- msg:
-		default:
-		}
-	}
-}
-
-type catchupMockStore struct {
-	StreamStore
-	ch chan uint64
-}
-
-func (s catchupMockStore) LoadMsg(seq uint64, sm *StoreMsg) (*StoreMsg, error) {
-	s.ch <- seq
-	return s.StreamStore.LoadMsg(seq, sm)
-}
-
-func TestJetStreamClusterLeaderAbortsCatchupOnFollowerError(t *testing.T) {
-	c := createJetStreamClusterExplicit(t, "JSC", 3)
-	defer c.shutdown()
-
-	nc, js := jsClientConnect(t, c.randomServer())
-	defer nc.Close()
-
-	cfg := &nats.StreamConfig{
-		Name:     "TEST",
-		Subjects: []string{"foo"},
-		Replicas: 3,
-	}
-	_, err := js.AddStream(cfg)
-	require_NoError(t, err)
-
-	c.waitOnStreamLeader(globalAccountName, "TEST")
-
-	payload := string(make([]byte, 1024))
-	total := 100
-	for i := 0; i < total; i++ {
-		sendStreamMsg(t, nc, "foo", payload)
-	}
-
-	c.waitOnAllCurrent()
-
-	// Get the stream leader
-	leader := c.streamLeader(globalAccountName, "TEST")
-	mset, err := leader.GlobalAccount().lookupStream("TEST")
-	require_NoError(t, err)
-
-	var syncSubj string
-	mset.mu.RLock()
-	if mset.syncSub != nil {
-		syncSubj = string(mset.syncSub.subject)
-	}
-	mset.mu.RUnlock()
-
-	if syncSubj == _EMPTY_ {
-		t.Fatal("Did not find the sync request subject")
-	}
-
-	// Setup the logger on the leader to make sure we capture the error and print
-	// and also stop the runCatchup.
-	l := &captureCatchupWarnLogger{ch: make(chan string, 10)}
-	leader.SetLogger(l, false, false)
-
-	// Set a fake message store that will allow us to verify
-	// a few things.
-	mset.mu.Lock()
-	orgMS := mset.store
-	ms := catchupMockStore{StreamStore: mset.store, ch: make(chan uint64)}
-	mset.store = ms
-	mset.mu.Unlock()
-
-	// Need the system account to simulate the sync request that we are going to send.
-	sysNC := natsConnect(t, c.randomServer().ClientURL(), nats.UserInfo("admin", "s3cr3t!"))
-	defer sysNC.Close()
-	// Setup a subscription to receive the messages sent by the leader.
-	sub := natsSubSync(t, sysNC, nats.NewInbox())
-	req := &streamSyncRequest{
-		FirstSeq: 1,
-		LastSeq:  uint64(total),
-		Peer:     "bozo", // Should be one of the node name, but does not matter here
-	}
-	b, _ := json.Marshal(req)
-	// Send the sync request and use our sub's subject for destination where leader
-	// needs to send messages to.
-	natsPubReq(t, sysNC, syncSubj, sub.Subject, b)
-
-	// The mock store is blocked loading the first message, so we need to consume
-	// the sequence before being able to receive the message in our sub.
-	if seq := <-ms.ch; seq != 1 {
-		t.Fatalf("Expected sequence to be 1, got %v", seq)
-	}
-
-	// Now consume and the leader should report the error and terminate runCatchup
-	msg := natsNexMsg(t, sub, time.Second)
-	msg.Respond([]byte("simulate error"))
-
-	select {
-	case <-l.ch:
-		// OK
-	case <-time.After(time.Second):
-		t.Fatal("Did not get the expected error")
-	}
-
-	// The mock store should be blocked in seq==2 now, but after consuming, it should
-	// abort the runCatchup.
-	if seq := <-ms.ch; seq != 2 {
-		t.Fatalf("Expected sequence to be 2, got %v", seq)
-	}
-	// We may have some more messages loaded as a race between when the sub will
-	// indicate that the catchup should stop and the part where we send messages
-	// in the batch, but we should likely not have sent all messages.
-	loaded := 0
-	for done := false; !done; {
-		select {
-		case <-ms.ch:
-			loaded++
-		case <-time.After(250 * time.Millisecond):
-			done = true
-		}
-	}
-	if loaded > 10 {
-		t.Fatalf("Too many messages were sent after detecting remote is done: %v", loaded)
-	}
-
-	ch := make(chan string, 1)
-	mset.mu.Lock()
-	mset.store = orgMS
-	leader.sysUnsubscribe(mset.syncSub)
-	mset.syncSub = nil
-	leader.systemSubscribe(syncSubj, _EMPTY_, false, mset.sysc, func(_ *subscription, _ *client, _ *Account, _, reply string, msg []byte) {
-		var sreq streamSyncRequest
-		if err := json.Unmarshal(msg, &sreq); err != nil {
-			return
-		}
-		select {
-		case ch <- reply:
-		default:
-		}
-	})
-	mset.mu.Unlock()
-	syncRepl := natsSubSync(t, sysNC, nats.NewInbox()+".>")
-	// Make sure our sub is propagated
-	time.Sleep(250 * time.Millisecond)
-
-	if v := leader.gcbTotal(); v != 0 {
-		t.Fatalf("Expected gcbTotal to be 0, got %v", v)
-	}
-
-	buf := make([]byte, 1_000_000)
-	n := runtime.Stack(buf, true)
-	if bytes.Contains(buf[:n], []byte("runCatchup")) {
-		t.Fatalf("Looks like runCatchup is still running:\n%s", buf[:n])
-	}
-
-	mset.mu.Lock()
-	var state StreamState
-	mset.store.FastState(&state)
-	snapshot := &streamSnapshot{
-		Msgs:     state.Msgs,
-		Bytes:    state.Bytes,
-		FirstSeq: state.FirstSeq,
-		LastSeq:  state.LastSeq + 1,
-	}
-	b, _ = json.Marshal(snapshot)
-	mset.node.SendSnapshot(b)
-	mset.mu.Unlock()
-
-	var sreqSubj string
-	select {
-	case sreqSubj = <-ch:
-	case <-time.After(time.Second):
-		t.Fatal("Did not receive sync request")
-	}
-
-	// Now send a message with a wrong sequence and expect to receive an error.
-	em := encodeStreamMsg("foo", _EMPTY_, nil, []byte("fail"), 102, time.Now().UnixNano())
-	leader.sendInternalMsgLocked(sreqSubj, syncRepl.Subject, nil, em)
-	msg = natsNexMsg(t, syncRepl, time.Second)
-	if len(msg.Data) == 0 {
-		t.Fatal("Expected err response from the remote")
-	}
-}
diff --git a/server/jetstream_helpers_test.go b/server/jetstream_helpers_test.go
index d3881ee8..f633ef34 100644
--- a/server/jetstream_helpers_test.go
+++ b/server/jetstream_helpers_test.go
@@ -20,10 +20,9 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
+	"io/ioutil"
 	"math/rand"
 	"net"
-	"net/url"
-	"os"
 	"strings"
 	"testing"
 	"time"
@@ -47,7 +46,6 @@ func init() {
 type supercluster struct {
 	t        *testing.T
 	clusters []*cluster
-	nproxies []*netProxy
 }
 
 func (sc *supercluster) shutdown() {
@@ -57,9 +55,6 @@ func (sc *supercluster) shutdown() {
 	for _, c := range sc.clusters {
 		shutdownCluster(c)
 	}
-	for _, np := range sc.nproxies {
-		np.stop()
-	}
 }
 
 func (sc *supercluster) randomServer() *Server {
@@ -265,11 +260,7 @@ var jsMixedModeGlobalAccountTempl = `
 var jsGWTempl = `%s{name: %s, urls: [%s]}`
 
 func createJetStreamTaggedSuperCluster(t *testing.T) *supercluster {
-	return createJetStreamTaggedSuperClusterWithGWProxy(t, nil)
-}
-
-func createJetStreamTaggedSuperClusterWithGWProxy(t *testing.T, gwm gwProxyMap) *supercluster {
-	sc := createJetStreamSuperClusterWithTemplateAndModHook(t, jsClusterTempl, 3, 3, nil, gwm)
+	sc := createJetStreamSuperCluster(t, 3, 3)
 	sc.waitOnPeerCount(9)
 
 	reset := func(s *Server) {
@@ -341,20 +332,10 @@ func createJetStreamSuperCluster(t *testing.T, numServersPer, numClusters int) *
 }
 
 func createJetStreamSuperClusterWithTemplate(t *testing.T, tmpl string, numServersPer, numClusters int) *supercluster {
-	return createJetStreamSuperClusterWithTemplateAndModHook(t, tmpl, numServersPer, numClusters, nil, nil)
-}
-
-// For doing proxyies in GWs.
-type gwProxy struct {
-	rtt  time.Duration
-	up   int
-	down int
+	return createJetStreamSuperClusterWithTemplateAndModHook(t, tmpl, numServersPer, numClusters, nil)
 }
 
-// Maps cluster names to proxy settings.
-type gwProxyMap map[string]*gwProxy
-
-func createJetStreamSuperClusterWithTemplateAndModHook(t *testing.T, tmpl string, numServersPer, numClusters int, modify modifyCb, gwm gwProxyMap) *supercluster {
+func createJetStreamSuperClusterWithTemplateAndModHook(t *testing.T, tmpl string, numServersPer, numClusters int, modify modifyCb) *supercluster {
 	t.Helper()
 	if numServersPer < 1 {
 		t.Fatalf("Number of servers must be >= 1")
@@ -374,30 +355,19 @@ func createJetStreamSuperClusterWithTemplateAndModHook(t *testing.T, tmpl string
 
 	cp, gp := startClusterPort, startGWPort
 	var clusters []*cluster
-	var nproxies []*netProxy
-	var gws []string
 
+	var gws []string
 	// Build GWs first, will be same for all servers.
 	for i, port := 1, gp; i <= numClusters; i++ {
 		cn := fmt.Sprintf("C%d", i)
-		var gwp *gwProxy
-		if len(gwm) > 0 {
-			gwp = gwm[cn]
-		}
 		var urls []string
 		for n := 0; n < numServersPer; n++ {
-			routeURL := fmt.Sprintf("nats-route://127.0.0.1:%d", port)
-			if gwp != nil {
-				np := createNetProxy(gwp.rtt, gwp.up, gwp.down, routeURL, false)
-				nproxies = append(nproxies, np)
-				routeURL = np.routeURL()
-			}
-			urls = append(urls, routeURL)
+			urls = append(urls, fmt.Sprintf("nats-route://127.0.0.1:%d", port))
 			port++
 		}
 		gws = append(gws, fmt.Sprintf(jsGWTempl, "\n\t\t\t", cn, strings.Join(urls, ",")))
 	}
-	gwconf := strings.Join(gws, _EMPTY_)
+	gwconf := strings.Join(gws, "")
 
 	for i := 1; i <= numClusters; i++ {
 		cn := fmt.Sprintf("C%d", i)
@@ -430,20 +400,15 @@ func createJetStreamSuperClusterWithTemplateAndModHook(t *testing.T, tmpl string
 		c.t = t
 	}
 
-	// Start any proxies.
-	for _, np := range nproxies {
-		np.start()
-	}
-
 	// Wait for the supercluster to be formed.
 	egws := numClusters - 1
 	for _, c := range clusters {
 		for _, s := range c.servers {
-			waitForOutboundGateways(t, s, egws, 10*time.Second)
+			waitForOutboundGateways(t, s, egws, 2*time.Second)
 		}
 	}
 
-	sc := &supercluster{t, clusters, nproxies}
+	sc := &supercluster{t, clusters}
 	sc.waitOnLeader()
 	sc.waitOnAllCurrent()
 
@@ -747,7 +712,7 @@ func createJetStreamClusterAndModHook(t *testing.T, tmpl string, clusterName, sn
 func (c *cluster) addInNewServer() *Server {
 	c.t.Helper()
 	sn := fmt.Sprintf("S-%d", len(c.servers)+1)
-	storeDir, _ := os.MkdirTemp(tempRoot, JetStreamStoreDir)
+	storeDir, _ := ioutil.TempDir(tempRoot, JetStreamStoreDir)
 	seedRoute := fmt.Sprintf("nats-route://127.0.0.1:%d", c.opts[0].Cluster.Port)
 	conf := fmt.Sprintf(jsClusterTempl, sn, storeDir, c.name, -1, seedRoute)
 	s, o := RunServerWithConfig(createConfFile(c.t, []byte(conf)))
@@ -986,7 +951,7 @@ func (s *Server) closeAndDisableLeafnodes() {
 		leafs = append(leafs, ln)
 	}
 	// Disable leafnodes for now.
-	s.leafDisableConnect = true
+	s.leafNodeEnabled = false
 	s.mu.Unlock()
 
 	for _, ln := range leafs {
@@ -1229,13 +1194,13 @@ func (c *cluster) waitOnServerHealthz(s *Server) {
 	c.t.Helper()
 	expires := time.Now().Add(30 * time.Second)
 	for time.Now().Before(expires) {
-		hs := s.healthz()
+		hs := s.healthz(nil)
 		if hs.Status == "ok" && hs.Error == _EMPTY_ {
 			return
 		}
 		time.Sleep(100 * time.Millisecond)
 	}
-	c.t.Fatalf("Expected server %q to eventually return healthz 'ok', but got %q", s, s.healthz().Error)
+	c.t.Fatalf("Expected server %q to eventually return healthz 'ok', but got %q", s, s.healthz(nil).Error)
 }
 
 func (c *cluster) waitOnServerCurrent(s *Server) {
@@ -1361,14 +1326,14 @@ func (c *cluster) removeJetStream(s *Server) {
 		}
 	}
 	cf := c.opts[index].ConfigFile
-	cb, _ := os.ReadFile(cf)
+	cb, _ := ioutil.ReadFile(cf)
 	var sb strings.Builder
 	for _, l := range strings.Split(string(cb), "\n") {
 		if !strings.HasPrefix(strings.TrimSpace(l), "jetstream") {
 			sb.WriteString(l + "\n")
 		}
 	}
-	if err := os.WriteFile(cf, []byte(sb.String()), 0644); err != nil {
+	if err := ioutil.WriteFile(cf, []byte(sb.String()), 0644); err != nil {
 		c.t.Fatalf("Error writing updated config file: %v", err)
 	}
 	if err := s.Reload(); err != nil {
@@ -1487,68 +1452,38 @@ func (o *consumer) setInActiveDeleteThreshold(dthresh time.Duration) error {
 type netProxy struct {
 	listener net.Listener
 	conns    []net.Conn
-	rtt      time.Duration
-	up       int
-	down     int
 	url      string
-	surl     string
 }
 
 func newNetProxy(rtt time.Duration, upRate, downRate int, serverURL string) *netProxy {
-	return createNetProxy(rtt, upRate, downRate, serverURL, true)
-}
-
-func createNetProxy(rtt time.Duration, upRate, downRate int, serverURL string, start bool) *netProxy {
 	hp := net.JoinHostPort("127.0.0.1", "0")
 	l, e := net.Listen("tcp", hp)
 	if e != nil {
 		panic(fmt.Sprintf("Error listening on port: %s, %q", hp, e))
 	}
 	port := l.Addr().(*net.TCPAddr).Port
-	proxy := &netProxy{
-		listener: l,
-		rtt:      rtt,
-		up:       upRate,
-		down:     downRate,
-		url:      fmt.Sprintf("nats://127.0.0.1:%d", port),
-		surl:     serverURL,
-	}
-	if start {
-		proxy.start()
-	}
-	return proxy
-}
-
-func (np *netProxy) start() {
+	proxy := &netProxy{listener: l}
 	go func() {
-		for {
-			client, err := np.listener.Accept()
-			if err != nil {
-				return
-			}
-			u, err := url.Parse(np.surl)
-			if err != nil {
-				panic(fmt.Sprintf("Could not parse server URL: %v", err))
-			}
-			server, err := net.DialTimeout("tcp", u.Host, time.Second)
-			if err != nil {
-				panic("Can't connect proxy to NATS server")
-			}
-			np.conns = append(np.conns, client, server)
-			go np.loop(np.rtt, np.up, client, server)
-			go np.loop(np.rtt, np.down, server, client)
+		client, err := l.Accept()
+		if err != nil {
+			return
+		}
+		server, err := net.DialTimeout("tcp", serverURL[7:], time.Second)
+		if err != nil {
+			panic("Can't connect to NATS server")
 		}
+		proxy.conns = append(proxy.conns, client, server)
+		go proxy.loop(rtt, upRate, client, server)
+		go proxy.loop(rtt, downRate, server, client)
 	}()
+	proxy.url = fmt.Sprintf("nats://127.0.0.1:%d", port)
+	return proxy
 }
 
 func (np *netProxy) clientURL() string {
 	return np.url
 }
 
-func (np *netProxy) routeURL() string {
-	return strings.Replace(np.url, "nats", "nats-route", 1)
-}
-
 func (np *netProxy) loop(rtt time.Duration, tbw int, r, w net.Conn) {
 	delay := rtt / 2
 	const rbl = 8192
@@ -1564,7 +1499,7 @@ func (np *netProxy) loop(rtt time.Duration, tbw int, r, w net.Conn) {
 			return
 		}
 		// RTT delays
-		if fr || time.Since(sr) > 250*time.Millisecond {
+		if fr || time.Since(sr) > 2*time.Millisecond {
 			fr = false
 			if delay > 0 {
 				time.Sleep(delay)
diff --git a/server/jetstream_jwt_test.go b/server/jetstream_jwt_test.go
index af30e02e..82bca608 100644
--- a/server/jetstream_jwt_test.go
+++ b/server/jetstream_jwt_test.go
@@ -326,7 +326,7 @@ func TestJetStreamJWTMove(t *testing.T) {
 						%s : %s
 					}
 				`, clustername, ojwt, syspub, storeDir, syspub, sysJwt)
-			}, nil)
+			})
 		defer sc.shutdown()
 
 		s := sc.serverByName("C1-S1")
@@ -813,7 +813,7 @@ func TestJetStreamJWTSysAccUpdateMixedMode(t *testing.T) {
 				operator: %s
 				system_account: %s
 				resolver: URL("%s%s")`, conf, ojwt, spub, ts.URL, basePath)
-		}, nil)
+		})
 	defer sc.shutdown()
 	disconnectChan := make(chan struct{}, 100)
 	defer close(disconnectChan)
diff --git a/server/jetstream_leafnode_test.go b/server/jetstream_leafnode_test.go
index 5343bbb9..64005041 100644
--- a/server/jetstream_leafnode_test.go
+++ b/server/jetstream_leafnode_test.go
@@ -18,6 +18,7 @@ package server
 
 import (
 	"fmt"
+	"io/ioutil"
 	"os"
 	"strings"
 	"testing"
@@ -484,7 +485,7 @@ leafnodes:{
 					require_NoError(t, err)
 				} else {
 					require_Error(t, err)
-					require_Contains(t, err.Error(), "no suitable peers for placement")
+					require_Contains(t, err.Error(), "insufficient resources")
 				}
 				ncL := natsConnect(t, fmt.Sprintf("nats://a1:a1@127.0.0.1:%d", sLA.opts.Port))
 				defer ncL.Close()
@@ -499,7 +500,7 @@ leafnodes:{
 					require_NoError(t, err)
 				} else {
 					require_Error(t, err)
-					require_Contains(t, err.Error(), "no suitable peers for placement")
+					require_Contains(t, err.Error(), "insufficient resources")
 				}
 			}
 			clusterLnCnt := func(expected int) error {
@@ -890,7 +891,7 @@ leafnodes: {
 		require_True(t, err == nats.ErrNoResponders)
 
 		// Add in default domain and restart server
-		require_NoError(t, os.WriteFile(confHub, []byte(fmt.Sprintf(tmplHub,
+		require_NoError(t, ioutil.WriteFile(confHub, []byte(fmt.Sprintf(tmplHub,
 			sHub.opts.Port,
 			"disabled",
 			"disabled",
@@ -913,7 +914,7 @@ leafnodes: {
 		sdHub := createDir(t, JetStreamStoreDir)
 		defer os.RemoveAll(sdHub)
 		jsEnabled := fmt.Sprintf(`{ domain: "%s", store_dir: '%s', max_mem: 100Mb, max_file: 100Mb }`, domain, sdHub)
-		require_NoError(t, os.WriteFile(confHub, []byte(fmt.Sprintf(tmplHub,
+		require_NoError(t, ioutil.WriteFile(confHub, []byte(fmt.Sprintf(tmplHub,
 			sHubUpd1.opts.Port,
 			"disabled",
 			jsEnabled,
@@ -934,7 +935,7 @@ leafnodes: {
 
 		// Enable jetstream in account A of hub
 		// This is a mis config, as you can't have it both ways, local jetstream but default to another one
-		require_NoError(t, os.WriteFile(confHub, []byte(fmt.Sprintf(tmplHub,
+		require_NoError(t, ioutil.WriteFile(confHub, []byte(fmt.Sprintf(tmplHub,
 			sHubUpd2.opts.Port,
 			"enabled",
 			jsEnabled,
@@ -1051,7 +1052,7 @@ leafnodes: {
 		require_True(t, err == nats.ErrNoResponders)
 
 		// Add in default domain and restart server
-		require_NoError(t, os.WriteFile(confHub, []byte(fmt.Sprintf(tmplHub,
+		require_NoError(t, ioutil.WriteFile(confHub, []byte(fmt.Sprintf(tmplHub,
 			sHub.opts.Port, ojwt, syspub, syspub, sysJwt, aPub, aJwt, sHub.opts.LeafNode.Port,
 			fmt.Sprintf(`default_js_domain: {%s:"%s"}`, aPub, domain))), 0664))
 
diff --git a/server/jetstream_super_cluster_test.go b/server/jetstream_super_cluster_test.go
index f6ada776..3d8086f6 100644
--- a/server/jetstream_super_cluster_test.go
+++ b/server/jetstream_super_cluster_test.go
@@ -17,12 +17,10 @@
 package server
 
 import (
-	"bytes"
 	"encoding/json"
 	"errors"
 	"fmt"
 	"math/rand"
-	"reflect"
 	"strings"
 	"sync"
 	"sync/atomic"
@@ -123,7 +121,7 @@ func TestJetStreamSuperClusterUniquePlacementTag(t *testing.T) {
 				"C2-S5": "az:1",
 			}
 			return conf + fmt.Sprintf("\nserver_tags: [cloud:%s-tag, %s]\n", clustername, azTag[serverName])
-		}, nil)
+		})
 	defer s.shutdown()
 
 	inDifferentAz := func(ci *nats.ClusterInfo) (bool, error) {
@@ -181,7 +179,7 @@ func TestJetStreamSuperClusterUniquePlacementTag(t *testing.T) {
 			si, err := js.AddStream(&nats.StreamConfig{Name: name, Replicas: test.replicas, Placement: test.placement})
 			if test.fail {
 				require_Error(t, err)
-				require_Contains(t, err.Error(), "no suitable peers for placement")
+				require_Equal(t, err.Error(), "insufficient resources")
 				return
 			}
 			require_NoError(t, err)
@@ -849,8 +847,8 @@ func TestJetStreamSuperClusterLeafNodesWithSharedSystemAccountAndDifferentDomain
 		Replicas:  2,
 		Placement: &nats.Placement{Cluster: pcn},
 	})
-	if err == nil || !strings.Contains(err.Error(), "no suitable peers for placement") {
-		t.Fatalf("Expected no suitable peers for placement, got: %v", err)
+	if err == nil || !strings.Contains(err.Error(), "insufficient resources") {
+		t.Fatalf("Expected insufficient resources, got: %v", err)
 	}
 }
 
@@ -1381,7 +1379,8 @@ func TestJetStreamSuperClusterOverflowPlacement(t *testing.T) {
 		MaxBytes:  2 * 1024 * 1024 * 1024,
 		Placement: &nats.Placement{Cluster: pcn},
 	})
-	require_Contains(t, err.Error(), "no suitable peers for placement")
+	require_Error(t, err, NewJSInsufficientResourcesError(), NewJSStorageResourcesExceededError())
+
 	// Now test actual overflow placement. So try again with no placement designation.
 	// This will test the peer picker's logic since they are updated at this point and the meta leader
 	// knows it can not place it in C2.
@@ -1497,7 +1496,7 @@ func TestJetStreamSuperClusterStreamTagPlacement(t *testing.T) {
 			Subjects:  []string{"foo"},
 			Placement: &nats.Placement{Tags: tags},
 		})
-		require_Contains(t, err.Error(), "no suitable peers for placement")
+		require_Error(t, err, NewJSInsufficientResourcesError())
 	}
 
 	placeErr("C1", []string{"cloud:GCP", "country:US"})
@@ -1836,7 +1835,7 @@ func TestJetStreamSuperClusterMovingStreamsAndConsumers(t *testing.T) {
 			si, err = js.StreamInfo("MOVE")
 			require_NoError(t, err)
 
-			if !reflect.DeepEqual(si.State, initialState) {
+			if si.State != initialState {
 				t.Fatalf("States do not match after migration:\n%+v\nvs\n%+v", si.State, initialState)
 			}
 
@@ -2036,7 +2035,7 @@ func TestJetStreamSuperClusterMovingStreamsWithMirror(t *testing.T) {
 		mi, err := js.StreamInfo("MIRROR")
 		require_NoError(t, err)
 
-		if !reflect.DeepEqual(si.State, mi.State) {
+		if si.State != mi.State {
 			return fmt.Errorf("Expected mirror to be the same, got %+v vs %+v", mi.State, si.State)
 		}
 		return nil
@@ -2329,7 +2328,7 @@ func TestJetStreamSuperClusterMaxHaAssets(t *testing.T) {
 	`, 3, 2,
 		func(serverName, clusterName, storeDir, conf string) string {
 			return conf
-		}, nil)
+		})
 	defer sc.shutdown()
 
 	// speed up statsz reporting
@@ -2381,8 +2380,7 @@ func TestJetStreamSuperClusterMaxHaAssets(t *testing.T) {
 	waitStatsz(3, 1)
 	_, err = js.AddStream(&nats.StreamConfig{Name: "S3", Replicas: 3, Placement: &nats.Placement{Cluster: "C1"}})
 	require_Error(t, err)
-	require_Contains(t, err.Error(), "no suitable peers for placement")
-	require_Contains(t, err.Error(), "misc: 3")
+	require_Equal(t, err.Error(), "insufficient resources")
 	require_NoError(t, js.DeleteStream("S1"))
 	waitStatsz(3, 2)
 	waitStatsz(3, 1)
@@ -2415,8 +2413,7 @@ func TestJetStreamSuperClusterMaxHaAssets(t *testing.T) {
 	require_Equal(t, err.Error(), "insufficient resources")
 	_, err = js.UpdateStream(&nats.StreamConfig{Name: "S2", Replicas: 3, Placement: &nats.Placement{Cluster: "C2"}})
 	require_Error(t, err)
-	require_Contains(t, err.Error(), "no suitable peers for placement")
-	require_Contains(t, err.Error(), "misc: 3")
+	require_Equal(t, err.Error(), "insufficient resources")
 }
 
 func TestJetStreamSuperClusterStreamAlternates(t *testing.T) {
@@ -2658,7 +2655,7 @@ func TestJetStreamSuperClusterMoveCancel(t *testing.T) {
 		func(serverName, clusterName, storeDir, conf string) string {
 			server[serverName] = struct{}{}
 			return fmt.Sprintf("%s\nserver_tags: [%s]", conf, serverName)
-		}, nil)
+		})
 	defer sc.shutdown()
 
 	// Client based API
@@ -2795,7 +2792,7 @@ func TestJetStreamSuperClusterDoubleStreamMove(t *testing.T) {
 		func(serverName, clusterName, storeDir, conf string) string {
 			server[serverName] = struct{}{}
 			return fmt.Sprintf("%s\nserver_tags: [%s]", conf, serverName)
-		}, nil)
+		})
 	defer sc.shutdown()
 
 	// Client based API
@@ -2993,7 +2990,7 @@ func TestJetStreamSuperClusterPeerEvacuationAndStreamReassignment(t *testing.T)
 	s := createJetStreamSuperClusterWithTemplateAndModHook(t, jsClusterTempl, 4, 2,
 		func(serverName, clusterName, storeDir, conf string) string {
 			return fmt.Sprintf("%s\nserver_tags: [cluster:%s, server:%s]", conf, clusterName, serverName)
-		}, nil)
+		})
 	defer s.shutdown()
 
 	c := s.clusterForName("C1")
@@ -3190,343 +3187,3 @@ func TestJetStreamSuperClusterPeerEvacuationAndStreamReassignment(t *testing.T)
 		test(3, []string{"cluster:C2"}, "C2", false, true)
 	})
 }
-
-func TestJetStreamSuperClusterMirrorInheritsAllowDirect(t *testing.T) {
-	sc := createJetStreamTaggedSuperCluster(t)
-	defer sc.shutdown()
-
-	nc, js := jsClientConnect(t, sc.randomServer())
-	defer nc.Close()
-
-	_, err := js.AddStream(&nats.StreamConfig{
-		Name:              "KV",
-		Subjects:          []string{"key.*"},
-		Placement:         &nats.Placement{Tags: []string{"cloud:aws", "country:us"}},
-		MaxMsgsPerSubject: 1,
-	})
-	require_NoError(t, err)
-
-	_, err = js.AddStream(&nats.StreamConfig{
-		Name:      "M",
-		Mirror:    &nats.StreamSource{Name: "KV"},
-		Placement: &nats.Placement{Tags: []string{"cloud:gcp", "country:uk"}},
-	})
-	require_NoError(t, err)
-
-	// Do direct grab for now.
-	resp, err := nc.Request(fmt.Sprintf(JSApiStreamInfoT, "M"), nil, time.Second)
-	require_NoError(t, err)
-	var si StreamInfo
-	err = json.Unmarshal(resp.Data, &si)
-	require_NoError(t, err)
-
-	if !si.Config.MirrorDirect {
-		t.Fatalf("Expected MirrorDirect to be inherited as true")
-	}
-}
-
-func TestJetStreamSuperClusterSystemLimitsPlacement(t *testing.T) {
-	const largeSystemLimit = 1024
-	const smallSystemLimit = 512
-
-	tmpl := `
-		listen: 127.0.0.1:-1
-		server_name: %s
-		jetstream: {
-			max_mem_store: _MAXMEM_
-			max_file_store: _MAXFILE_
-			store_dir: '%s',
-		}
-		server_tags: [
-			_TAG_
-		]
-		leaf {
-			listen: 127.0.0.1:-1
-		}
-		cluster {
-			name: %s
-			listen: 127.0.0.1:%d
-			routes = [%s]
-		}
-
-		accounts { $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } }
-	`
-	storeCnf := func(serverName, clusterName, storeDir, conf string) string {
-		switch {
-		case strings.HasPrefix(serverName, "C1"):
-			conf = strings.Replace(conf, "_MAXMEM_", fmt.Sprint(largeSystemLimit), 1)
-			conf = strings.Replace(conf, "_MAXFILE_", fmt.Sprint(largeSystemLimit), 1)
-			return strings.Replace(conf, "_TAG_", serverName, 1)
-		case strings.HasPrefix(serverName, "C2"):
-			conf = strings.Replace(conf, "_MAXMEM_", fmt.Sprint(smallSystemLimit), 1)
-			conf = strings.Replace(conf, "_MAXFILE_", fmt.Sprint(smallSystemLimit), 1)
-			return strings.Replace(conf, "_TAG_", serverName, 1)
-		default:
-			return conf
-		}
-	}
-
-	sCluster := createJetStreamSuperClusterWithTemplateAndModHook(t, tmpl, 3, 2, storeCnf, nil)
-	defer sCluster.shutdown()
-
-	requestLeaderStepDown := func(clientURL string) error {
-		nc, err := nats.Connect(clientURL)
-		if err != nil {
-			return err
-		}
-		defer nc.Close()
-
-		ncResp, err := nc.Request(JSApiLeaderStepDown, nil, 3*time.Second)
-		if err != nil {
-			return err
-		}
-
-		var resp JSApiLeaderStepDownResponse
-		if err := json.Unmarshal(ncResp.Data, &resp); err != nil {
-			return err
-		}
-		if resp.Error != nil {
-			return resp.Error
-		}
-		if !resp.Success {
-			return fmt.Errorf("leader step down request not successful")
-		}
-
-		return nil
-	}
-
-	// Force large cluster to be leader
-	var largeLeader *Server
-	err := checkForErr(15*time.Second, 500*time.Millisecond, func() error {
-		// Range over cluster A, which is the large cluster.
-		servers := sCluster.clusters[0].servers
-		for _, s := range servers {
-			if s.JetStreamIsLeader() {
-				largeLeader = s
-				return nil
-			}
-		}
-
-		if err := requestLeaderStepDown(servers[0].ClientURL()); err != nil {
-			return fmt.Errorf("failed to request leader step down: %s", err)
-		}
-		return fmt.Errorf("leader is not in large cluster")
-	})
-	if err != nil {
-		t.Skipf("failed to get desired layout: %s", err)
-	}
-
-	getStreams := func(jsm nats.JetStreamManager) []string {
-		var streams []string
-		for s := range jsm.StreamNames() {
-			streams = append(streams, s)
-		}
-		return streams
-	}
-	nc, js := jsClientConnect(t, largeLeader)
-	defer nc.Close()
-
-	cases := []struct {
-		name           string
-		storage        nats.StorageType
-		createMaxBytes int64
-		serverTag      string
-		wantErr        bool
-	}{
-		{
-			name:           "file create large stream on small cluster b0",
-			storage:        nats.FileStorage,
-			createMaxBytes: smallSystemLimit + 1,
-			serverTag:      "C2-S1",
-			wantErr:        true,
-		},
-		{
-			name:           "memory create large stream on small cluster b0",
-			storage:        nats.MemoryStorage,
-			createMaxBytes: smallSystemLimit + 1,
-			serverTag:      "C2-S1",
-			wantErr:        true,
-		},
-		{
-			name:           "file create large stream on small cluster b1",
-			storage:        nats.FileStorage,
-			createMaxBytes: smallSystemLimit + 1,
-			serverTag:      "C2-S2",
-			wantErr:        true,
-		},
-		{
-			name:           "memory create large stream on small cluster b1",
-			storage:        nats.MemoryStorage,
-			createMaxBytes: smallSystemLimit + 1,
-			serverTag:      "C2-S2",
-			wantErr:        true,
-		},
-		{
-			name:           "file create large stream on small cluster b2",
-			storage:        nats.FileStorage,
-			createMaxBytes: smallSystemLimit + 1,
-			serverTag:      "C2-S3",
-			wantErr:        true,
-		},
-		{
-			name:           "memory create large stream on small cluster b2",
-			storage:        nats.MemoryStorage,
-			createMaxBytes: smallSystemLimit + 1,
-			serverTag:      "C2-S3",
-			wantErr:        true,
-		},
-		{
-			name:           "file create large stream on large cluster a0",
-			storage:        nats.FileStorage,
-			createMaxBytes: smallSystemLimit + 1,
-			serverTag:      "C1-S1",
-		},
-		{
-			name:           "memory create large stream on large cluster a0",
-			storage:        nats.MemoryStorage,
-			createMaxBytes: smallSystemLimit + 1,
-			serverTag:      "C1-S1",
-		},
-		{
-			name:           "file create large stream on large cluster a1",
-			storage:        nats.FileStorage,
-			createMaxBytes: smallSystemLimit + 1,
-			serverTag:      "C1-S2",
-		},
-		{
-			name:           "memory create large stream on large cluster a1",
-			storage:        nats.MemoryStorage,
-			createMaxBytes: smallSystemLimit + 1,
-			serverTag:      "C1-S2",
-		},
-		{
-			name:           "file create large stream on large cluster a2",
-			storage:        nats.FileStorage,
-			createMaxBytes: smallSystemLimit + 1,
-			serverTag:      "C1-S3",
-		},
-		{
-			name:           "memory create large stream on large cluster a2",
-			storage:        nats.MemoryStorage,
-			createMaxBytes: smallSystemLimit + 1,
-			serverTag:      "C1-S3",
-		},
-	}
-	for i := 0; i < len(cases) && !t.Failed(); i++ {
-		c := cases[i]
-		t.Run(c.name, func(st *testing.T) {
-			var clusterName string
-			if strings.HasPrefix(c.serverTag, "a") {
-				clusterName = "cluster-a"
-			} else if strings.HasPrefix(c.serverTag, "b") {
-				clusterName = "cluster-b"
-			}
-
-			if s := getStreams(js); len(s) != 0 {
-				st.Fatalf("unexpected stream count, got=%d, want=0", len(s))
-			}
-
-			streamName := fmt.Sprintf("TEST-%s", c.serverTag)
-			si, err := js.AddStream(&nats.StreamConfig{
-				Name:     streamName,
-				Subjects: []string{"foo"},
-				Storage:  c.storage,
-				MaxBytes: c.createMaxBytes,
-				Placement: &nats.Placement{
-					Cluster: clusterName,
-					Tags:    []string{c.serverTag},
-				},
-			})
-			if c.wantErr && err == nil {
-				if s := getStreams(js); len(s) != 1 {
-					st.Logf("unexpected stream count, got=%d, want=1, streams=%v", len(s), s)
-				}
-
-				cfg := si.Config
-				st.Fatalf("unexpected success, maxBytes=%d, cluster=%s, tags=%v",
-					cfg.MaxBytes, cfg.Placement.Cluster, cfg.Placement.Tags)
-			} else if !c.wantErr && err != nil {
-				if s := getStreams(js); len(s) != 0 {
-					st.Logf("unexpected stream count, got=%d, want=0, streams=%v", len(s), s)
-				}
-
-				require_NoError(st, err)
-			}
-
-			if err == nil {
-				if s := getStreams(js); len(s) != 1 {
-					st.Fatalf("unexpected stream count, got=%d, want=1", len(s))
-				}
-			}
-			// Delete regardless.
-			js.DeleteStream(streamName)
-		})
-	}
-}
-
-func TestJetStreamSuperClusterStreamCathupLongRTT(t *testing.T) {
-	skip(t)
-
-	// Make C2 far away.
-	gwm := gwProxyMap{
-		"C2": &gwProxy{
-			rtt:  300 * time.Millisecond,
-			up:   1 * 1024 * 1024 * 1024, // 1gbit
-			down: 1 * 1024 * 1024 * 1024, // 1gbit
-		},
-	}
-	sc := createJetStreamTaggedSuperClusterWithGWProxy(t, gwm)
-	defer sc.shutdown()
-
-	nc, js := jsClientConnect(t, sc.randomServer())
-	defer nc.Close()
-
-	cfg := &nats.StreamConfig{
-		Name:              "TEST",
-		Subjects:          []string{"chunk.*"},
-		Placement:         &nats.Placement{Tags: []string{"cloud:aws", "country:us"}},
-		Replicas:          3,
-		MaxMsgsPerSubject: 1,
-	}
-
-	// Place a stream in C1.
-	_, err := js.AddStream(cfg)
-	require_NoError(t, err)
-
-	chunk := bytes.Repeat([]byte("Z"), 1000*1024) // ~1MB
-	// 256 MB
-	for i := 0; i < 256; i++ {
-		subj := fmt.Sprintf("chunk.%d", i)
-		js.PublishAsync(subj, chunk)
-	}
-	select {
-	case <-js.PublishAsyncComplete():
-	case <-time.After(5 * time.Second):
-		t.Fatalf("Did not receive completion signal")
-	}
-
-	// C2, slow RTT.
-	cfg.Placement = &nats.Placement{Tags: []string{"cloud:gcp", "country:uk"}}
-	_, err = js.UpdateStream(cfg)
-	require_NoError(t, err)
-
-	checkFor(t, 10*time.Second, 100*time.Millisecond, func() error {
-		si, err := js.StreamInfo("TEST")
-		if err != nil {
-			return err
-		}
-		if si.Cluster.Name != "C2" {
-			return fmt.Errorf("Wrong cluster: %q", si.Cluster.Name)
-		}
-		if si.Cluster.Leader == _EMPTY_ {
-			return fmt.Errorf("No leader yet")
-		} else if !strings.HasPrefix(si.Cluster.Leader, "C2-") {
-			return fmt.Errorf("Wrong leader: %q", si.Cluster.Leader)
-		}
-		// Now we want to see that we shrink back to original.
-		if len(si.Cluster.Replicas) != cfg.Replicas-1 {
-			return fmt.Errorf("Expected %d replicas, got %d", cfg.Replicas-1, len(si.Cluster.Replicas))
-		}
-		return nil
-	})
-}
diff --git a/server/jetstream_test.go b/server/jetstream_test.go
index 9331862f..b4bcd71d 100644
--- a/server/jetstream_test.go
+++ b/server/jetstream_test.go
@@ -24,6 +24,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"math"
 	"math/rand"
 	"net/http"
@@ -92,7 +93,7 @@ func RunBasicJetStreamServer() *Server {
 	opts := DefaultTestOptions
 	opts.Port = -1
 	opts.JetStream = true
-	tdir, _ := os.MkdirTemp(tempRoot, "jstests-storedir-")
+	tdir, _ := ioutil.TempDir(tempRoot, "jstests-storedir-")
 	opts.StoreDir = tdir
 	return RunServer(&opts)
 }
@@ -4128,7 +4129,7 @@ func TestJetStreamSnapshots(t *testing.T) {
 		t.Fatalf("Error getting snapshot: %v", err)
 	}
 	zr := sr.Reader
-	snapshot, err := io.ReadAll(zr)
+	snapshot, err := ioutil.ReadAll(zr)
 	if err != nil {
 		t.Fatalf("Error reading snapshot")
 	}
@@ -7031,6 +7032,245 @@ func TestJetStreamSystemLimitsPlacement(t *testing.T) {
 	}
 }
 
+func TestJetStreamSuperClusterSystemLimitsPlacement(t *testing.T) {
+	const largeSystemLimit = 1024
+	const smallSystemLimit = 512
+
+	tmpl := `
+		listen: 127.0.0.1:-1
+		server_name: %s
+		jetstream: {
+			max_mem_store: _MAXMEM_
+			max_file_store: _MAXFILE_
+			store_dir: '%s',
+		}
+		server_tags: [
+			_TAG_
+		]
+		leaf {
+			listen: 127.0.0.1:-1
+		}
+		cluster {
+			name: %s
+			listen: 127.0.0.1:%d
+			routes = [%s]
+		}
+
+		accounts { $SYS { users = [ { user: "admin", pass: "s3cr3t!" } ] } }
+	`
+	storeCnf := func(serverName, clusterName, storeDir, conf string) string {
+		switch {
+		case strings.HasPrefix(serverName, "C1"):
+			conf = strings.Replace(conf, "_MAXMEM_", fmt.Sprint(largeSystemLimit), 1)
+			conf = strings.Replace(conf, "_MAXFILE_", fmt.Sprint(largeSystemLimit), 1)
+			return strings.Replace(conf, "_TAG_", serverName, 1)
+		case strings.HasPrefix(serverName, "C2"):
+			conf = strings.Replace(conf, "_MAXMEM_", fmt.Sprint(smallSystemLimit), 1)
+			conf = strings.Replace(conf, "_MAXFILE_", fmt.Sprint(smallSystemLimit), 1)
+			return strings.Replace(conf, "_TAG_", serverName, 1)
+		default:
+			return conf
+		}
+	}
+
+	sCluster := createJetStreamSuperClusterWithTemplateAndModHook(t, tmpl, 3, 2, storeCnf)
+	defer sCluster.shutdown()
+
+	requestLeaderStepDown := func(clientURL string) error {
+		nc, err := nats.Connect(clientURL)
+		if err != nil {
+			return err
+		}
+		defer nc.Close()
+
+		ncResp, err := nc.Request(JSApiLeaderStepDown, nil, 3*time.Second)
+		if err != nil {
+			return err
+		}
+
+		var resp JSApiLeaderStepDownResponse
+		if err := json.Unmarshal(ncResp.Data, &resp); err != nil {
+			return err
+		}
+		if resp.Error != nil {
+			return resp.Error
+		}
+		if !resp.Success {
+			return fmt.Errorf("leader step down request not successful")
+		}
+
+		return nil
+	}
+
+	// Force large cluster to be leader
+	var largeLeader *Server
+	err := checkForErr(15*time.Second, 500*time.Millisecond, func() error {
+		// Range over cluster A, which is the large cluster.
+		servers := sCluster.clusters[0].servers
+		for _, s := range servers {
+			if s.JetStreamIsLeader() {
+				largeLeader = s
+				return nil
+			}
+		}
+
+		if err := requestLeaderStepDown(servers[0].ClientURL()); err != nil {
+			return fmt.Errorf("failed to request leader step down: %s", err)
+		}
+		return fmt.Errorf("leader is not in large cluster")
+	})
+	if err != nil {
+		t.Skipf("failed to get desired layout: %s", err)
+	}
+
+	getStreams := func(jsm nats.JetStreamManager) []string {
+		var streams []string
+		for s := range jsm.StreamNames() {
+			streams = append(streams, s)
+		}
+		return streams
+	}
+	nc, js := jsClientConnect(t, largeLeader)
+	defer nc.Close()
+
+	cases := []struct {
+		name           string
+		storage        nats.StorageType
+		createMaxBytes int64
+		serverTag      string
+		wantErr        bool
+	}{
+		{
+			name:           "file create large stream on small cluster b0",
+			storage:        nats.FileStorage,
+			createMaxBytes: smallSystemLimit + 1,
+			serverTag:      "C2-S1",
+			wantErr:        true,
+		},
+		{
+			name:           "memory create large stream on small cluster b0",
+			storage:        nats.MemoryStorage,
+			createMaxBytes: smallSystemLimit + 1,
+			serverTag:      "C2-S1",
+			wantErr:        true,
+		},
+		{
+			name:           "file create large stream on small cluster b1",
+			storage:        nats.FileStorage,
+			createMaxBytes: smallSystemLimit + 1,
+			serverTag:      "C2-S2",
+			wantErr:        true,
+		},
+		{
+			name:           "memory create large stream on small cluster b1",
+			storage:        nats.MemoryStorage,
+			createMaxBytes: smallSystemLimit + 1,
+			serverTag:      "C2-S2",
+			wantErr:        true,
+		},
+		{
+			name:           "file create large stream on small cluster b2",
+			storage:        nats.FileStorage,
+			createMaxBytes: smallSystemLimit + 1,
+			serverTag:      "C2-S3",
+			wantErr:        true,
+		},
+		{
+			name:           "memory create large stream on small cluster b2",
+			storage:        nats.MemoryStorage,
+			createMaxBytes: smallSystemLimit + 1,
+			serverTag:      "C2-S3",
+			wantErr:        true,
+		},
+		{
+			name:           "file create large stream on large cluster a0",
+			storage:        nats.FileStorage,
+			createMaxBytes: smallSystemLimit + 1,
+			serverTag:      "C1-S1",
+		},
+		{
+			name:           "memory create large stream on large cluster a0",
+			storage:        nats.MemoryStorage,
+			createMaxBytes: smallSystemLimit + 1,
+			serverTag:      "C1-S1",
+		},
+		{
+			name:           "file create large stream on large cluster a1",
+			storage:        nats.FileStorage,
+			createMaxBytes: smallSystemLimit + 1,
+			serverTag:      "C1-S2",
+		},
+		{
+			name:           "memory create large stream on large cluster a1",
+			storage:        nats.MemoryStorage,
+			createMaxBytes: smallSystemLimit + 1,
+			serverTag:      "C1-S2",
+		},
+		{
+			name:           "file create large stream on large cluster a2",
+			storage:        nats.FileStorage,
+			createMaxBytes: smallSystemLimit + 1,
+			serverTag:      "C1-S3",
+		},
+		{
+			name:           "memory create large stream on large cluster a2",
+			storage:        nats.MemoryStorage,
+			createMaxBytes: smallSystemLimit + 1,
+			serverTag:      "C1-S3",
+		},
+	}
+	for i := 0; i < len(cases) && !t.Failed(); i++ {
+		c := cases[i]
+		t.Run(c.name, func(st *testing.T) {
+			var clusterName string
+			if strings.HasPrefix(c.serverTag, "a") {
+				clusterName = "cluster-a"
+			} else if strings.HasPrefix(c.serverTag, "b") {
+				clusterName = "cluster-b"
+			}
+
+			if s := getStreams(js); len(s) != 0 {
+				st.Fatalf("unexpected stream count, got=%d, want=0", len(s))
+			}
+
+			streamName := fmt.Sprintf("TEST-%s", c.serverTag)
+			si, err := js.AddStream(&nats.StreamConfig{
+				Name:     streamName,
+				Subjects: []string{"foo"},
+				Storage:  c.storage,
+				MaxBytes: c.createMaxBytes,
+				Placement: &nats.Placement{
+					Cluster: clusterName,
+					Tags:    []string{c.serverTag},
+				},
+			})
+			if c.wantErr && err == nil {
+				if s := getStreams(js); len(s) != 1 {
+					st.Logf("unexpected stream count, got=%d, want=1, streams=%v", len(s), s)
+				}
+
+				cfg := si.Config
+				st.Fatalf("unexpected success, maxBytes=%d, cluster=%s, tags=%v",
+					cfg.MaxBytes, cfg.Placement.Cluster, cfg.Placement.Tags)
+			} else if !c.wantErr && err != nil {
+				if s := getStreams(js); len(s) != 0 {
+					st.Logf("unexpected stream count, got=%d, want=0, streams=%v", len(s), s)
+				}
+
+				require_NoError(st, err)
+			}
+
+			if err == nil {
+				if s := getStreams(js); len(s) != 1 {
+					st.Fatalf("unexpected stream count, got=%d, want=1", len(s))
+				}
+			}
+			// Delete regardless.
+			js.DeleteStream(streamName)
+		})
+	}
+}
+
 func TestJetStreamStreamLimitUpdate(t *testing.T) {
 	s := RunBasicJetStreamServer()
 	if config := s.JetStreamConfig(); config != nil {
@@ -9439,7 +9679,7 @@ func TestJetStreamMultipleAccountsBasics(t *testing.T) {
 			},
 		}
 	`)
-	if err := os.WriteFile(conf, newConf, 0600); err != nil {
+	if err := ioutil.WriteFile(conf, newConf, 0600); err != nil {
 		t.Fatalf("Error rewriting server's config file: %v", err)
 	}
 	if err := s.Reload(); err != nil {
@@ -9573,7 +9813,7 @@ func TestJetStreamStoreDirectoryFix(t *testing.T) {
 
 	// Now move stuff up from the jetstream directory etc.
 	jssd := filepath.Join(sd, JetStreamStoreDir)
-	fis, _ := os.ReadDir(jssd)
+	fis, _ := ioutil.ReadDir(jssd)
 	// This will be accounts, move them up one directory.
 	for _, fi := range fis {
 		os.Rename(filepath.Join(jssd, fi.Name()), filepath.Join(sd, fi.Name()))
@@ -11284,7 +11524,7 @@ func TestJetStreamConfigReloadWithGlobalAccount(t *testing.T) {
 		t.Fatalf("Expected %d msgs after restart, got %d", toSend, si.State.Msgs)
 	}
 
-	if err := os.WriteFile(conf, []byte(fmt.Sprintf(template, "pwd2")), 0666); err != nil {
+	if err := ioutil.WriteFile(conf, []byte(fmt.Sprintf(template, "pwd2")), 0666); err != nil {
 		t.Fatalf("Error writing config: %v", err)
 	}
 
@@ -12400,7 +12640,7 @@ func TestJetStreamServerEncryption(t *testing.T) {
 	// Make sure we can not find any plaintext strings in the target file.
 	checkFor := func(fn string, strs ...string) {
 		t.Helper()
-		data, err := os.ReadFile(fn)
+		data, err := ioutil.ReadFile(fn)
 		if err != nil {
 			t.Fatalf("Unexpected error: %v", err)
 		}
@@ -12429,7 +12669,7 @@ func TestJetStreamServerEncryption(t *testing.T) {
 		checkKeyFile(filepath.Join(sdir, "obs", "dlc", JetStreamMetaFileKey))
 		checkFor(filepath.Join(sdir, "obs", "dlc", JetStreamMetaFile), "TEST", "dlc", "foo", "bar", "baz", "max_msgs", "ack_policy")
 		// Load and see if we can parse the consumer state.
-		state, err := os.ReadFile(filepath.Join(sdir, "obs", "dlc", "o.dat"))
+		state, err := ioutil.ReadFile(filepath.Join(sdir, "obs", "dlc", "o.dat"))
 		if err != nil {
 			t.Fatalf("Unexpected error: %v", err)
 		}
@@ -12493,7 +12733,7 @@ func TestJetStreamServerEncryption(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Error getting snapshot: %v", err)
 	}
-	snapshot, err := io.ReadAll(sr.Reader)
+	snapshot, err := ioutil.ReadAll(sr.Reader)
 	if err != nil {
 		t.Fatalf("Error reading snapshot")
 	}
@@ -14768,11 +15008,11 @@ func TestJetStreamPullConsumerCrossAccountsAndLeafNodes(t *testing.T) {
 }
 
 // This test is to explicitly test for all combinations of pull consumer behavior.
-//  1. Long poll, will be used to emulate push. A request is only invalidated when batch is filled, it expires, or we lose interest.
-//  2. Batch 1, will return no messages or a message. Works today.
-//  3. Conditional wait, or one shot. This is what the clients do when the do a fetch().
-//     They expect to wait up to a given time for any messages but will return once they have any to deliver, so parital fills.
-//  4. Try, which never waits at all ever.
+// 1. Long poll, will be used to emulate push. A request is only invalidated when batch is filled, it expires, or we lose interest.
+// 2. Batch 1, will return no messages or a message. Works today.
+// 3. Conditional wait, or one shot. This is what the clients do when the do a fetch().
+//    They expect to wait up to a given time for any messages but will return once they have any to deliver, so parital fills.
+// 4. Try, which never waits at all ever.
 func TestJetStreamPullConsumersOneShotBehavior(t *testing.T) {
 	s := RunBasicJetStreamServer()
 	if config := s.JetStreamConfig(); config != nil {
@@ -15618,7 +15858,7 @@ func TestJetStreamStorageReservedBytes(t *testing.T) {
 	opts.JetStream = true
 	opts.JetStreamMaxMemory = systemLimit
 	opts.JetStreamMaxStore = systemLimit
-	tdir, _ := os.MkdirTemp(tempRoot, "jstests-storedir-")
+	tdir, _ := ioutil.TempDir(tempRoot, "jstests-storedir-")
 	opts.StoreDir = tdir
 	opts.HTTPPort = -1
 	s := RunServer(&opts)
@@ -16136,7 +16376,7 @@ func TestJetStreamRemoveExternalSource(t *testing.T) {
 	lu, err := url.Parse(fmt.Sprintf("nats://127.0.0.1:%d", ho.LeafNode.Port))
 	require_NoError(t, err)
 
-	tdir, _ := os.MkdirTemp(tempRoot, "jstests-storedir-")
+	tdir, _ := ioutil.TempDir(tempRoot, "jstests-storedir-")
 	defer removeDir(t, tdir)
 	lo1 := DefaultTestOptions
 	lo1.Port = 4111 //-1
@@ -16148,7 +16388,7 @@ func TestJetStreamRemoveExternalSource(t *testing.T) {
 	l1 := RunServer(&lo1)
 	defer l1.Shutdown()
 
-	tdir, _ = os.MkdirTemp(tempRoot, "jstests-storedir-")
+	tdir, _ = ioutil.TempDir(tempRoot, "jstests-storedir-")
 	defer removeDir(t, tdir)
 	lo2 := DefaultTestOptions
 	lo2.Port = 2111 //-1
@@ -17129,7 +17369,7 @@ func TestJetStreamWorkQueueSourceRestart(t *testing.T) {
 	defer s.Shutdown()
 
 	checkFor(t, 10*time.Second, 200*time.Millisecond, func() error {
-		hs := s.healthz()
+		hs := s.healthz(nil)
 		if hs.Status == "ok" && hs.Error == _EMPTY_ {
 			return nil
 		}
@@ -17250,7 +17490,7 @@ func TestJetStreamWorkQueueSourceNamingRestart(t *testing.T) {
 	defer s.Shutdown()
 
 	checkFor(t, 10*time.Second, 200*time.Millisecond, func() error {
-		hs := s.healthz()
+		hs := s.healthz(nil)
 		if hs.Status == "ok" && hs.Error == _EMPTY_ {
 			return nil
 		}
@@ -17268,6 +17508,22 @@ func TestJetStreamWorkQueueSourceNamingRestart(t *testing.T) {
 	}
 }
 
+func TestJetStreamDisabledHealthz(t *testing.T) {
+	s := RunRandClientPortServer()
+	defer s.Shutdown()
+
+	if s.JetStreamEnabled() {
+		t.Fatalf("Expected JetStream to be disabled")
+	}
+
+	hs := s.healthz(&HealthzOptions{JSEnabled: true})
+	if hs.Status == "unavailable" && hs.Error == NewJSNotEnabledError().Error() {
+		return
+	}
+
+	t.Fatalf("Expected healthz to return error if JetStream is disabled, got status: %s", hs.Status)
+}
+
 func TestJetStreamPullMaxBytes(t *testing.T) {
 	s := RunBasicJetStreamServer()
 	if config := s.JetStreamConfig(); config != nil {
@@ -18727,164 +18983,3 @@ func TestJetStreamMirrorUpdatesNotSupported(t *testing.T) {
 		t.Fatalf("Expected error %q, got %q", NewJSStreamMirrorNotUpdatableError(), err)
 	}
 }
-
-func TestJetStreamDirectGetBySubject(t *testing.T) {
-	conf := createConfFile(t, []byte(`
-		listen: 127.0.0.1:-1
-		jetstream: {max_mem_store: 64GB, max_file_store: 10TB}
-
-		ONLYME = {
-			publish = { allow = "$JS.API.DIRECT.GET.KV.vid.22.>"}
-		}
-
-		accounts: {
-			A: {
-				jetstream: enabled
-				users: [
-					{ user: admin, password: s3cr3t },
-					{ user: user, password: pwd, permissions: $ONLYME},
-				]
-			},
-		}
-	`))
-	defer removeFile(t, conf)
-
-	s, _ := RunServerWithConfig(conf)
-	if config := s.JetStreamConfig(); config != nil {
-		defer removeDir(t, config.StoreDir)
-	}
-	defer s.Shutdown()
-
-	nc, js := jsClientConnect(t, s, nats.UserInfo("admin", "s3cr3t"))
-	defer nc.Close()
-
-	// Do by hand for now.
-	cfg := &StreamConfig{
-		Name:        "KV",
-		Storage:     MemoryStorage,
-		Subjects:    []string{"vid.*.>"},
-		MaxMsgsPer:  1,
-		AllowDirect: true,
-	}
-	addStream(t, nc, cfg)
-
-	// Add in mirror as well.
-	cfg = &StreamConfig{
-		Name:         "M",
-		Storage:      MemoryStorage,
-		Mirror:       &StreamSource{Name: "KV"},
-		MirrorDirect: true,
-	}
-	addStream(t, nc, cfg)
-
-	v22 := "vid.22.speed"
-	v33 := "vid.33.speed"
-	_, err := js.Publish(v22, []byte("100"))
-	require_NoError(t, err)
-	_, err = js.Publish(v33, []byte("55"))
-	require_NoError(t, err)
-
-	// User the restricted user.
-	nc, _ = jsClientConnect(t, s, nats.UserInfo("user", "pwd"))
-	defer nc.Close()
-
-	errCh := make(chan error, 10)
-	nc.SetErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, e error) {
-		select {
-		case errCh <- e:
-		default:
-		}
-	})
-
-	getSubj := fmt.Sprintf(JSDirectGetLastBySubjectT, "KV", v22)
-	m, err := nc.Request(getSubj, nil, time.Second)
-	require_NoError(t, err)
-	require_True(t, string(m.Data) == "100")
-
-	// Now attempt to access vid 33 data..
-	getSubj = fmt.Sprintf(JSDirectGetLastBySubjectT, "KV", v33)
-	_, err = nc.Request(getSubj, nil, 200*time.Millisecond)
-	require_Error(t, err) // timeout here.
-
-	select {
-	case e := <-errCh:
-		if !strings.HasPrefix(e.Error(), "nats: Permissions Violation") {
-			t.Fatalf("Expected a permissions violation but got %v", e)
-		}
-	case <-time.After(time.Second):
-		t.Fatalf("Expected to get a permissions error, got none")
-	}
-
-	// Now make sure mirrors are doing right thing with new way as well.
-	var sawMirror bool
-	getSubj = fmt.Sprintf(JSDirectGetLastBySubjectT, "KV", v22)
-	for i := 0; i < 100; i++ {
-		m, err := nc.Request(getSubj, nil, time.Second)
-		require_NoError(t, err)
-		if shdr := m.Header.Get(JSStream); shdr == "M" {
-			sawMirror = true
-			break
-		}
-	}
-	if !sawMirror {
-		t.Fatalf("Expected to see the mirror respond at least once")
-	}
-}
-
-// v2.9 will move to direct gets, this tests that we autoset them and auto-promote older streams.
-// This is keyed off a config setting for MaxMsgsPerSubject.
-func TestJetStreamDirectGetAutoSet(t *testing.T) {
-	s := RunBasicJetStreamServer()
-	if config := s.JetStreamConfig(); config != nil {
-		defer removeDir(t, config.StoreDir)
-	}
-	defer s.Shutdown()
-
-	nc, js := jsClientConnect(t, s)
-	defer nc.Close()
-
-	_, err := js.AddStream(&nats.StreamConfig{
-		Name:              "KV",
-		Subjects:          []string{"key.*"},
-		MaxMsgsPerSubject: 1,
-	})
-	require_NoError(t, err)
-
-	_, err = js.Publish("key.22", []byte("22"))
-	require_NoError(t, err)
-
-	// Make sure direct get was auto turned on.
-	subj := fmt.Sprintf(JSDirectMsgGetT, "KV")
-	req := []byte(`{"last_by_subj": "key.22"}`)
-	m, err := nc.Request(subj, req, time.Second)
-	require_NoError(t, err)
-	require_True(t, string(m.Data) == "22")
-
-	// New direct with key in subject.
-	subj = fmt.Sprintf(JSDirectGetLastBySubjectT, "KV", "key.22")
-	m, err = nc.Request(subj, nil, time.Second)
-	require_NoError(t, err)
-	require_True(t, string(m.Data) == "22")
-
-	// Make sure mirrors inherit.
-	_, err = js.AddStream(&nats.StreamConfig{
-		Name:   "M",
-		Mirror: &nats.StreamSource{Name: "KV"},
-	})
-	require_NoError(t, err)
-
-	// Now make sure mirrors are doing right thing with new way as well.
-	var sawMirror bool
-	subj = fmt.Sprintf(JSDirectGetLastBySubjectT, "KV", "key.22")
-	for i := 0; i < 100; i++ {
-		m, err := nc.Request(subj, nil, time.Second)
-		require_NoError(t, err)
-		if shdr := m.Header.Get(JSStream); shdr == "M" {
-			sawMirror = true
-			break
-		}
-	}
-	if !sawMirror {
-		t.Fatalf("Expected to see the mirror respond at least once")
-	}
-}
diff --git a/server/jwt_test.go b/server/jwt_test.go
index 561b7e95..48e8a99e 100644
--- a/server/jwt_test.go
+++ b/server/jwt_test.go
@@ -20,6 +20,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"net/http"
 	"net/http/httptest"
 	"os"
@@ -3157,7 +3158,7 @@ func TestJWTExpiredUserCredentialsRenewal(t *testing.T) {
 		conf := createFile(t, "")
 		fName := conf.Name()
 		conf.Close()
-		if err := os.WriteFile(fName, content, 0666); err != nil {
+		if err := ioutil.WriteFile(fName, content, 0666); err != nil {
 			removeFile(t, fName)
 			t.Fatalf("Error writing conf file: %v", err)
 		}
@@ -3242,7 +3243,7 @@ func TestJWTExpiredUserCredentialsRenewal(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Error encoding credentials: %v", err)
 	}
-	if err := os.WriteFile(chainedFile, creds, 0666); err != nil {
+	if err := ioutil.WriteFile(chainedFile, creds, 0666); err != nil {
 		t.Fatalf("Error writing conf file: %v", err)
 	}
 
@@ -3316,7 +3317,7 @@ func require_JWTPresent(t *testing.T, dir string, pub string) {
 
 func require_JWTEqual(t *testing.T, dir string, pub string, jwt string) {
 	t.Helper()
-	content, err := os.ReadFile(filepath.Join(dir, pub+".jwt"))
+	content, err := ioutil.ReadFile(filepath.Join(dir, pub+".jwt"))
 	require_NoError(t, err)
 	require_Equal(t, string(content), jwt)
 }
@@ -3325,7 +3326,7 @@ func createDir(t testing.TB, prefix string) string {
 	t.Helper()
 	err := os.MkdirAll(tempRoot, 0700)
 	require_NoError(t, err)
-	dir, err := os.MkdirTemp(tempRoot, prefix)
+	dir, err := ioutil.TempDir(tempRoot, prefix)
 	require_NoError(t, err)
 	return dir
 }
@@ -3339,7 +3340,7 @@ func createFile(t *testing.T, prefix string) *os.File {
 
 func createFileAtDir(t *testing.T, dir, prefix string) *os.File {
 	t.Helper()
-	f, err := os.CreateTemp(dir, prefix)
+	f, err := ioutil.TempFile(dir, prefix)
 	require_NoError(t, err)
 	return f
 }
@@ -3360,7 +3361,7 @@ func removeFile(t *testing.T, p string) {
 
 func writeJWT(t *testing.T, dir string, pub string, jwt string) {
 	t.Helper()
-	err := os.WriteFile(filepath.Join(dir, pub+".jwt"), []byte(jwt), 0644)
+	err := ioutil.WriteFile(filepath.Join(dir, pub+".jwt"), []byte(jwt), 0644)
 	require_NoError(t, err)
 }
 
diff --git a/server/leafnode_test.go b/server/leafnode_test.go
index 22e229a5..ac26e88f 100644
--- a/server/leafnode_test.go
+++ b/server/leafnode_test.go
@@ -4398,107 +4398,3 @@ func TestLeafNodeAuthConfigReload(t *testing.T) {
 	// Reload here should work ok.
 	reloadUpdateConfig(t, s, conf, template)
 }
-
-func TestLeafNodeSignatureCB(t *testing.T) {
-	content := `
-		port: -1
-		server_name: OP
-		operator = "../test/configs/nkeys/op.jwt"
-		resolver = MEMORY
-		listen: "127.0.0.1:-1"
-		leafnodes {
-			listen: "127.0.0.1:-1"
-		}
-	`
-	conf := createConfFile(t, []byte(content))
-	s, opts := RunServerWithConfig(conf)
-	defer removeFile(t, conf)
-	defer s.Shutdown()
-
-	_, akp := createAccount(s)
-	kp, _ := nkeys.CreateUser()
-	pub, _ := kp.PublicKey()
-	nuc := jwt.NewUserClaims(pub)
-	ujwt, err := nuc.Encode(akp)
-	if err != nil {
-		t.Fatalf("Error generating user JWT: %v", err)
-	}
-
-	lopts := &DefaultTestOptions
-	u, err := url.Parse(fmt.Sprintf("nats://%s:%d", opts.LeafNode.Host, opts.LeafNode.Port))
-	if err != nil {
-		t.Fatalf("Error parsing url: %v", err)
-	}
-	remote := &RemoteLeafOpts{URLs: []*url.URL{u}}
-	remote.SignatureCB = func(nonce []byte) (string, []byte, error) {
-		return "", nil, fmt.Errorf("on purpose")
-	}
-	lopts.LeafNode.Remotes = []*RemoteLeafOpts{remote}
-	lopts.LeafNode.ReconnectInterval = 100 * time.Millisecond
-	sl := RunServer(lopts)
-	defer sl.Shutdown()
-
-	slog := &captureErrorLogger{errCh: make(chan string, 10)}
-	sl.SetLogger(slog, false, false)
-
-	// Now check that the leafnode got the error that the callback returned.
-	select {
-	case err := <-slog.errCh:
-		if !strings.Contains(err, "on purpose") {
-			t.Fatalf("Expected error from cb, got %v", err)
-		}
-	case <-time.After(time.Second):
-		t.Fatal("Did not get expected error")
-	}
-
-	sl.Shutdown()
-	// Now check what happens if the connection is closed while in the callback.
-	blockCh := make(chan struct{})
-	remote.SignatureCB = func(nonce []byte) (string, []byte, error) {
-		<-blockCh
-		sig, err := kp.Sign(nonce)
-		return ujwt, sig, err
-	}
-	sl = RunServer(lopts)
-	defer sl.Shutdown()
-
-	// Recreate the logger so that we are sure not to have possible previous errors
-	slog = &captureErrorLogger{errCh: make(chan string, 10)}
-	sl.SetLogger(slog, false, false)
-
-	// Get the leaf connection from the temp clients map and close it.
-	checkFor(t, time.Second, 15*time.Millisecond, func() error {
-		var c *client
-		sl.grMu.Lock()
-		for _, cli := range sl.grTmpClients {
-			c = cli
-		}
-		sl.grMu.Unlock()
-		if c == nil {
-			return fmt.Errorf("Client still not found in temp map")
-		}
-		c.closeConnection(ClientClosed)
-		return nil
-	})
-
-	// Release the callback, and check we get the appropriate error.
-	close(blockCh)
-	select {
-	case err := <-slog.errCh:
-		if !strings.Contains(err, ErrConnectionClosed.Error()) {
-			t.Fatalf("Expected error that connection was closed, got %v", err)
-		}
-	case <-time.After(time.Second):
-		t.Fatal("Did not get expected error")
-	}
-
-	sl.Shutdown()
-	// Change to a good CB and now it should work
-	remote.SignatureCB = func(nonce []byte) (string, []byte, error) {
-		sig, err := kp.Sign(nonce)
-		return ujwt, sig, err
-	}
-	sl = RunServer(lopts)
-	defer sl.Shutdown()
-	checkLeafNodeConnected(t, sl)
-}
diff --git a/server/log_test.go b/server/log_test.go
index e32c3556..d41fba4b 100644
--- a/server/log_test.go
+++ b/server/log_test.go
@@ -15,6 +15,7 @@ package server
 
 import (
 	"bytes"
+	"io/ioutil"
 	"os"
 	"runtime"
 	"strings"
@@ -108,7 +109,7 @@ func TestReOpenLogFile(t *testing.T) {
 	expectedStr := "This is a Notice"
 	s.Noticef(expectedStr)
 	// Check content of log
-	buf, err := os.ReadFile(s.opts.LogFile)
+	buf, err := ioutil.ReadFile(s.opts.LogFile)
 	if err != nil {
 		t.Fatalf("Error reading file: %v", err)
 	}
@@ -122,7 +123,7 @@ func TestReOpenLogFile(t *testing.T) {
 	// Now re-open LogFile
 	s.ReOpenLogFile()
 	// Content should indicate that we have re-opened the log
-	buf, err = os.ReadFile(s.opts.LogFile)
+	buf, err = ioutil.ReadFile(s.opts.LogFile)
 	if err != nil {
 		t.Fatalf("Error reading file: %v", err)
 	}
@@ -131,7 +132,7 @@ func TestReOpenLogFile(t *testing.T) {
 	}
 	// Make sure we can append to the log
 	s.Noticef("New message")
-	buf, err = os.ReadFile(s.opts.LogFile)
+	buf, err = ioutil.ReadFile(s.opts.LogFile)
 	if err != nil {
 		t.Fatalf("Error reading file: %v", err)
 	}
@@ -162,7 +163,7 @@ func TestFileLoggerSizeLimitAndReopen(t *testing.T) {
 	s.ReOpenLogFile()
 
 	// Content should indicate that we have re-opened the log
-	buf, err := os.ReadFile(s.opts.LogFile)
+	buf, err := ioutil.ReadFile(s.opts.LogFile)
 	if err != nil {
 		t.Fatalf("Error reading file: %v", err)
 	}
@@ -181,7 +182,7 @@ func TestFileLoggerSizeLimitAndReopen(t *testing.T) {
 	}
 	s.Noticef(string(txt))
 
-	buf, err = os.ReadFile(s.opts.LogFile)
+	buf, err = ioutil.ReadFile(s.opts.LogFile)
 	if err != nil {
 		t.Fatalf("Error reading file: %v", err)
 	}
diff --git a/server/monitor_test.go b/server/monitor_test.go
index d6f756f0..71f10951 100644
--- a/server/monitor_test.go
+++ b/server/monitor_test.go
@@ -19,12 +19,11 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"io"
+	"io/ioutil"
 	"math/rand"
 	"net"
 	"net/http"
 	"net/url"
-	"os"
 	"reflect"
 	"runtime"
 	"sort"
@@ -159,7 +158,7 @@ func readBodyEx(t *testing.T, url string, status int, content string) []byte {
 	if ct != content {
 		stackFatalf(t, "Expected %s content-type, got %s\n", content, ct)
 	}
-	body, err := io.ReadAll(resp.Body)
+	body, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		stackFatalf(t, "Got an error reading the body: %v\n", err)
 	}
@@ -1673,7 +1672,7 @@ func TestHandleRoot(t *testing.T) {
 		t.Fatalf("Expected a %d response, got %d\n", http.StatusOK, resp.StatusCode)
 	}
 
-	body, err := io.ReadAll(resp.Body)
+	body, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		t.Fatalf("Expected no error reading body: Got %v\n", err)
 	}
@@ -2011,7 +2010,7 @@ func TestConcurrentMonitoring(t *testing.T) {
 					ech <- fmt.Sprintf("Expected application/json content-type, got %s\n", ct)
 					return
 				}
-				if _, err := io.ReadAll(resp.Body); err != nil {
+				if _, err := ioutil.ReadAll(resp.Body); err != nil {
 					ech <- fmt.Sprintf("Got an error reading the body: %v\n", err)
 					return
 				}
@@ -2405,7 +2404,7 @@ func Benchmark_VarzHttp(b *testing.B) {
 			b.Fatalf("Expected no error: Got %v\n", err)
 		}
 		defer resp.Body.Close()
-		body, err := io.ReadAll(resp.Body)
+		body, err := ioutil.ReadAll(resp.Body)
 		if err != nil {
 			b.Fatalf("Got an error reading the body: %v\n", err)
 		}
@@ -3596,7 +3595,7 @@ func TestMonitorOpJWT(t *testing.T) {
 	sa, _ := RunServerWithConfig(conf)
 	defer sa.Shutdown()
 
-	theJWT, err := os.ReadFile("../test/configs/nkeys/op.jwt")
+	theJWT, err := ioutil.ReadFile("../test/configs/nkeys/op.jwt")
 	require_NoError(t, err)
 	theJWT = []byte(strings.Split(string(theJWT), "\n")[1])
 	claim, err := jwt.DecodeOperatorClaims(string(theJWT))
diff --git a/server/mqtt_test.go b/server/mqtt_test.go
index 3ecedc0e..b2a1d6bd 100644
--- a/server/mqtt_test.go
+++ b/server/mqtt_test.go
@@ -18,7 +18,6 @@ import (
 	"bytes"
 	"crypto/tls"
 	"encoding/json"
-	"errors"
 	"fmt"
 	"io"
 	"math/rand"
@@ -5754,8 +5753,8 @@ func TestMQTTStreamReplicasInsufficientResources(t *testing.T) {
 
 	select {
 	case e := <-l.errCh:
-		if !strings.Contains(e, fmt.Sprintf("%d", NewJSClusterNoPeersError(errors.New("")).ErrCode)) {
-			t.Fatalf("Expected error regarding no peers error, got %v", e)
+		if !strings.Contains(e, NewJSInsufficientResourcesError().Description) {
+			t.Fatalf("Expected error regarding insufficient resources, got %v", e)
 		}
 	case <-time.After(2 * time.Second):
 		t.Fatalf("Did not get the error regarding replicas count")
diff --git a/server/norace_test.go b/server/norace_test.go
index 4f9d49fb..e14ef24b 100644
--- a/server/norace_test.go
+++ b/server/norace_test.go
@@ -24,6 +24,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"math/rand"
 	"net"
 	"net/http"
@@ -1674,7 +1675,7 @@ func TestNoRaceJetStreamSuperClusterMixedModeMirrors(t *testing.T) {
 				conf = strings.ReplaceAll(conf, "leaf: { ", "#leaf: { ")
 			}
 			return conf
-		}, nil)
+		})
 	defer sc.shutdown()
 
 	// Connect our client to a non JS server
@@ -1978,7 +1979,7 @@ func TestNoRaceJetStreamSuperClusterMixedModeSources(t *testing.T) {
 				conf = strings.ReplaceAll(conf, "leaf: { ", "#leaf: { ")
 			}
 			return conf
-		}, nil)
+		})
 	defer sc.shutdown()
 
 	// Connect our client to a non JS server
@@ -2901,13 +2902,13 @@ func TestNoRaceCompressedConnz(t *testing.T) {
 				t.Fatalf("Unexpected error: %v", err)
 			}
 			defer zr.Close()
-			buf, err = io.ReadAll(zr)
+			buf, err = ioutil.ReadAll(zr)
 			if err != nil && err != io.ErrUnexpectedEOF {
 				t.Fatalf("Unexpected error: %v", err)
 			}
 		case "snappy", "s2":
 			sr := s2.NewReader(bytes.NewReader(buf))
-			buf, err = io.ReadAll(sr)
+			buf, err = ioutil.ReadAll(sr)
 			if err != nil && err != io.ErrUnexpectedEOF {
 				t.Fatalf("Unexpected error: %v", err)
 			}
@@ -4209,7 +4210,7 @@ func TestNoRaceJetStreamClusterHealthz(t *testing.T) {
 		resp, err := http.Get(url)
 		require_NoError(t, err)
 		defer resp.Body.Close()
-		body, err := io.ReadAll(resp.Body)
+		body, err := ioutil.ReadAll(resp.Body)
 		require_NoError(t, err)
 		var hs HealthStatus
 		err = json.Unmarshal(body, &hs)
@@ -5182,19 +5183,10 @@ func TestNoRaceJetStreamClusterInterestPullConsumerStreamLimitBug(t *testing.T)
 	for i := 0; i < 100; i++ {
 		go func() {
 			defer wg.Done()
-			nc := natsConnect(t, c.randomServer().ClientURL())
+			nc, js := jsClientConnect(t, c.randomServer())
 			defer nc.Close()
 
-			js, err := nc.JetStream(nats.MaxWait(time.Second))
-			require_NoError(t, err)
-
-			var sub *nats.Subscription
-			for j := 0; j < 5; j++ {
-				sub, err = js.PullSubscribe("foo", "dur")
-				if err == nil {
-					break
-				}
-			}
+			sub, err := js.PullSubscribe("foo", "dur")
 			require_NoError(t, err)
 
 			for {
@@ -5315,7 +5307,7 @@ func TestNoRaceJetStreamClusterDirectAccessAllPeersSubs(t *testing.T) {
 	updateStream(t, nc, cfg)
 
 	// Wait for the stream to register the new replicas and have a leader.
-	checkFor(t, 20*time.Second, 500*time.Millisecond, func() error {
+	checkFor(t, 10*time.Second, 500*time.Millisecond, func() error {
 		si, err := js.StreamInfo("TEST")
 		if err != nil {
 			return err
diff --git a/server/opts_test.go b/server/opts_test.go
index 1a78aaad..f612e94a 100644
--- a/server/opts_test.go
+++ b/server/opts_test.go
@@ -19,6 +19,7 @@ import (
 	"encoding/json"
 	"flag"
 	"fmt"
+	"io/ioutil"
 	"net/url"
 	"os"
 	"reflect"
@@ -1133,7 +1134,7 @@ func TestBadNkeyConfig(t *testing.T) {
     authorization {
       users = [ {nkey: "Ufoo"}]
     }`
-	if err := os.WriteFile(confFileName, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(confFileName, []byte(content), 0666); err != nil {
 		t.Fatalf("Error writing config file: %v", err)
 	}
 	if _, err := ProcessConfigFile(confFileName); err == nil {
@@ -1150,7 +1151,7 @@ func TestNkeyWithPassConfig(t *testing.T) {
         {nkey: "UDKTV7HZVYJFJN64LLMYQBUR6MTNNYCDC3LAZH4VHURW3GZLL3FULBXV", pass: "foo"}
       ]
     }`
-	if err := os.WriteFile(confFileName, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(confFileName, []byte(content), 0666); err != nil {
 		t.Fatalf("Error writing config file: %v", err)
 	}
 	if _, err := ProcessConfigFile(confFileName); err == nil {
@@ -1167,7 +1168,7 @@ func TestTokenWithUserPass(t *testing.T) {
 		pass: password
 		token: $2a$11$whatever
 	}`
-	if err := os.WriteFile(confFileName, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(confFileName, []byte(content), 0666); err != nil {
 		t.Fatalf("Error writing config file: %v", err)
 	}
 	_, err := ProcessConfigFile(confFileName)
@@ -1189,7 +1190,7 @@ func TestTokenWithUsers(t *testing.T) {
 			{user: test, password: test}
 		]
 	}`
-	if err := os.WriteFile(confFileName, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(confFileName, []byte(content), 0666); err != nil {
 		t.Fatalf("Error writing config file: %v", err)
 	}
 	_, err := ProcessConfigFile(confFileName)
@@ -1204,7 +1205,7 @@ func TestTokenWithUsers(t *testing.T) {
 func TestParseWriteDeadline(t *testing.T) {
 	confFile := "test.conf"
 	defer removeFile(t, confFile)
-	if err := os.WriteFile(confFile, []byte("write_deadline: \"1x\""), 0666); err != nil {
+	if err := ioutil.WriteFile(confFile, []byte("write_deadline: \"1x\""), 0666); err != nil {
 		t.Fatalf("Error writing config file: %v", err)
 	}
 	_, err := ProcessConfigFile(confFile)
@@ -1215,7 +1216,7 @@ func TestParseWriteDeadline(t *testing.T) {
 		t.Fatalf("Expected error related to parsing, got %v", err)
 	}
 	removeFile(t, confFile)
-	if err := os.WriteFile(confFile, []byte("write_deadline: \"1s\""), 0666); err != nil {
+	if err := ioutil.WriteFile(confFile, []byte("write_deadline: \"1s\""), 0666); err != nil {
 		t.Fatalf("Error writing config file: %v", err)
 	}
 	opts, err := ProcessConfigFile(confFile)
@@ -1233,7 +1234,7 @@ func TestParseWriteDeadline(t *testing.T) {
 		os.Stdout = oldStdout
 	}()
 	os.Stdout = w
-	if err := os.WriteFile(confFile, []byte("write_deadline: 2"), 0666); err != nil {
+	if err := ioutil.WriteFile(confFile, []byte("write_deadline: 2"), 0666); err != nil {
 		t.Fatalf("Error writing config file: %v", err)
 	}
 	opts, err = ProcessConfigFile(confFile)
@@ -2108,7 +2109,7 @@ func TestParsingGateways(t *testing.T) {
 	`
 	file := "server_config_gateways.conf"
 	defer removeFile(t, file)
-	if err := os.WriteFile(file, []byte(content), 0600); err != nil {
+	if err := ioutil.WriteFile(file, []byte(content), 0600); err != nil {
 		t.Fatalf("Error writing config file: %v", err)
 	}
 	opts, err := ProcessConfigFile(file)
@@ -2362,7 +2363,7 @@ func TestParsingGatewaysErrors(t *testing.T) {
 		t.Run(test.name, func(t *testing.T) {
 			file := fmt.Sprintf("server_config_gateways_%s.conf", test.name)
 			defer removeFile(t, file)
-			if err := os.WriteFile(file, []byte(test.content), 0600); err != nil {
+			if err := ioutil.WriteFile(file, []byte(test.content), 0600); err != nil {
 				t.Fatalf("Error writing config file: %v", err)
 			}
 			_, err := ProcessConfigFile(file)
@@ -2569,7 +2570,7 @@ func TestLargeMaxControlLine(t *testing.T) {
 	content := `
     max_control_line = 3000000000
     `
-	if err := os.WriteFile(confFileName, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(confFileName, []byte(content), 0666); err != nil {
 		t.Fatalf("Error writing config file: %v", err)
 	}
 	if _, err := ProcessConfigFile(confFileName); err == nil {
diff --git a/server/reload_test.go b/server/reload_test.go
index bd9da248..7be0b6d2 100644
--- a/server/reload_test.go
+++ b/server/reload_test.go
@@ -20,6 +20,7 @@ import (
 	"encoding/json"
 	"flag"
 	"fmt"
+	"io/ioutil"
 	"log"
 	"net"
 	"net/http"
@@ -40,7 +41,7 @@ import (
 
 func newServerWithConfig(t *testing.T, configFile string) (*Server, *Options, string) {
 	t.Helper()
-	content, err := os.ReadFile(configFile)
+	content, err := ioutil.ReadFile(configFile)
 	if err != nil {
 		t.Fatalf("Error loading file: %v", err)
 	}
@@ -69,7 +70,7 @@ func createConfFile(t *testing.T, content []byte) string {
 	conf := createFile(t, "")
 	fName := conf.Name()
 	conf.Close()
-	if err := os.WriteFile(fName, content, 0666); err != nil {
+	if err := ioutil.WriteFile(fName, content, 0666); err != nil {
 		removeFile(t, fName)
 		t.Fatalf("Error writing conf file: %v", err)
 	}
@@ -78,7 +79,7 @@ func createConfFile(t *testing.T, content []byte) string {
 
 func runReloadServerWithConfig(t *testing.T, configFile string) (*Server, *Options, string) {
 	t.Helper()
-	content, err := os.ReadFile(configFile)
+	content, err := ioutil.ReadFile(configFile)
 	if err != nil {
 		t.Fatalf("Error loading file: %v", err)
 	}
@@ -96,7 +97,7 @@ func runReloadServerWithContent(t *testing.T, content []byte) (*Server, *Options
 
 func changeCurrentConfigContent(t *testing.T, curConfig, newConfig string) {
 	t.Helper()
-	content, err := os.ReadFile(newConfig)
+	content, err := ioutil.ReadFile(newConfig)
 	if err != nil {
 		t.Fatalf("Error loading file: %v", err)
 	}
@@ -105,7 +106,7 @@ func changeCurrentConfigContent(t *testing.T, curConfig, newConfig string) {
 
 func changeCurrentConfigContentWithNewContent(t *testing.T, curConfig string, content []byte) {
 	t.Helper()
-	if err := os.WriteFile(curConfig, content, 0666); err != nil {
+	if err := ioutil.WriteFile(curConfig, content, 0666); err != nil {
 		t.Fatalf("Error writing config: %v", err)
 	}
 }
@@ -265,7 +266,7 @@ func TestConfigReload(t *testing.T) {
 	}
 	platformConf := filepath.Join(dir, "platform.conf")
 	defer removeFile(t, platformConf)
-	if err := os.WriteFile(platformConf, content, 0666); err != nil {
+	if err := ioutil.WriteFile(platformConf, content, 0666); err != nil {
 		t.Fatalf("Unable to write config file: %v", err)
 	}
 
@@ -1626,7 +1627,7 @@ func TestConfigReloadClusterRemoveSolicitedRoutes(t *testing.T) {
 
 func reloadUpdateConfig(t *testing.T, s *Server, conf, content string) {
 	t.Helper()
-	if err := os.WriteFile(conf, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(conf, []byte(content), 0666); err != nil {
 		t.Fatalf("Error creating config file: %v", err)
 	}
 	if err := s.Reload(); err != nil {
@@ -1786,7 +1787,7 @@ func TestConfigReloadMaxSubsUnsupported(t *testing.T) {
 	defer removeFile(t, conf)
 	defer s.Shutdown()
 
-	if err := os.WriteFile(conf, []byte(`max_subs: 10`), 0666); err != nil {
+	if err := ioutil.WriteFile(conf, []byte(`max_subs: 10`), 0666); err != nil {
 		t.Fatalf("Error writing config file: %v", err)
 	}
 	if err := s.Reload(); err == nil {
@@ -4137,7 +4138,7 @@ func TestLoggingReload(t *testing.T) {
 
 	check := func(filename string, valid func([]byte) bool) {
 		t.Helper()
-		log, err := os.ReadFile(filename)
+		log, err := ioutil.ReadFile(filename)
 		if err != nil {
 			t.Fatalf("Error reading log file %s: %v\n", filename, err)
 		}
diff --git a/server/routes_test.go b/server/routes_test.go
index 0b552e9a..69205ae7 100644
--- a/server/routes_test.go
+++ b/server/routes_test.go
@@ -1526,67 +1526,3 @@ func TestSubjectRenameViaJetStreamAck(t *testing.T) {
 		t.Fatalf("Expected error")
 	}
 }
-
-func TestClusterQueueGroupWeightTrackingLeak(t *testing.T) {
-	o := DefaultOptions()
-	o.ServerName = "A"
-	s := RunServer(o)
-	defer s.Shutdown()
-
-	o2 := DefaultOptions()
-	o2.ServerName = "B"
-	o2.Routes = RoutesFromStr(fmt.Sprintf("nats://127.0.0.1:%d", o.Cluster.Port))
-	s2 := RunServer(o2)
-	defer s2.Shutdown()
-
-	nc := natsConnect(t, s.ClientURL())
-	defer nc.Close()
-
-	// Create a queue subscription
-	sub := natsQueueSubSync(t, nc, "foo", "bar")
-
-	// Check on s0 that we have the proper queue weight info
-	acc := s.GlobalAccount()
-
-	check := func(present bool, expected int32) {
-		t.Helper()
-		checkFor(t, time.Second, 15*time.Millisecond, func() error {
-			acc.mu.RLock()
-			v, ok := acc.lqws["foo bar"]
-			acc.mu.RUnlock()
-			if present {
-				if !ok {
-					return fmt.Errorf("the key is not present")
-				}
-				if v != expected {
-					return fmt.Errorf("lqws doest not contain expected value of %v: %v", expected, v)
-				}
-			} else if ok {
-				return fmt.Errorf("the key is present with value %v and should not be", v)
-			}
-			return nil
-		})
-	}
-	check(true, 1)
-
-	// Now unsub, and it should be removed, not just be 0
-	sub.Unsubscribe()
-	check(false, 0)
-
-	// Still make sure that the subject interest is gone from both servers.
-	checkSubGone := func(s *Server) {
-		t.Helper()
-		checkFor(t, time.Second, 15*time.Millisecond, func() error {
-			acc := s.GlobalAccount()
-			acc.mu.RLock()
-			res := acc.sl.Match("foo")
-			acc.mu.RUnlock()
-			if res != nil && len(res.qsubs) > 0 {
-				return fmt.Errorf("Found queue sub on foo for server %v", s)
-			}
-			return nil
-		})
-	}
-	checkSubGone(s)
-	checkSubGone(s2)
-}
diff --git a/server/server_test.go b/server/server_test.go
index 5021e868..22900e64 100644
--- a/server/server_test.go
+++ b/server/server_test.go
@@ -22,6 +22,7 @@ import (
 	"flag"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"net"
 	"net/url"
 	"os"
@@ -1624,7 +1625,7 @@ func TestConnectErrorReports(t *testing.T) {
 	checkContent := func(t *testing.T, txt string, attempt int, shouldBeThere bool) {
 		t.Helper()
 		checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
-			content, err := os.ReadFile(log)
+			content, err := ioutil.ReadFile(log)
 			if err != nil {
 				return fmt.Errorf("Error reading log file: %v", err)
 			}
@@ -1672,7 +1673,7 @@ func TestConnectErrorReports(t *testing.T) {
 	checkLeafContent := func(t *testing.T, txt, host string, attempt int, shouldBeThere bool) {
 		t.Helper()
 		checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
-			content, err := os.ReadFile(log)
+			content, err := ioutil.ReadFile(log)
 			if err != nil {
 				return fmt.Errorf("Error reading log file: %v", err)
 			}
@@ -1788,7 +1789,7 @@ func TestReconnectErrorReports(t *testing.T) {
 	checkContent := func(t *testing.T, txt string, attempt int, shouldBeThere bool) {
 		t.Helper()
 		checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
-			content, err := os.ReadFile(log)
+			content, err := ioutil.ReadFile(log)
 			if err != nil {
 				return fmt.Errorf("Error reading log file: %v", err)
 			}
@@ -1851,7 +1852,7 @@ func TestReconnectErrorReports(t *testing.T) {
 	checkLeafContent := func(t *testing.T, txt, host string, attempt int, shouldBeThere bool) {
 		t.Helper()
 		checkFor(t, 2*time.Second, 15*time.Millisecond, func() error {
-			content, err := os.ReadFile(log)
+			content, err := ioutil.ReadFile(log)
 			if err != nil {
 				return fmt.Errorf("Error reading log file: %v", err)
 			}
@@ -1959,7 +1960,7 @@ func TestServerLogsConfigurationFile(t *testing.T) {
 	s := RunServer(o)
 	s.Shutdown()
 
-	log, err := os.ReadFile(file.Name())
+	log, err := ioutil.ReadFile(file.Name())
 	if err != nil {
 		t.Fatalf("Error reading log file: %v", err)
 	}
diff --git a/server/signal_test.go b/server/signal_test.go
index bc3ba113..1f359755 100644
--- a/server/signal_test.go
+++ b/server/signal_test.go
@@ -19,6 +19,7 @@ package server
 import (
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"os"
 	"os/exec"
 	"strings"
@@ -51,7 +52,7 @@ func TestSignalToReOpenLogFile(t *testing.T) {
 	// Add a trace
 	expectedStr := "This is a Notice"
 	s.Noticef(expectedStr)
-	buf, err := os.ReadFile(logFile)
+	buf, err := ioutil.ReadFile(logFile)
 	if err != nil {
 		t.Fatalf("Error reading file: %v", err)
 	}
@@ -66,7 +67,7 @@ func TestSignalToReOpenLogFile(t *testing.T) {
 	syscall.Kill(syscall.Getpid(), syscall.SIGUSR1)
 	// Wait a bit for action to be performed
 	time.Sleep(500 * time.Millisecond)
-	buf, err = os.ReadFile(logFile)
+	buf, err = ioutil.ReadFile(logFile)
 	if err != nil {
 		t.Fatalf("Error reading file: %v", err)
 	}
diff --git a/server/websocket_test.go b/server/websocket_test.go
index cffbf22a..f3ea54e0 100644
--- a/server/websocket_test.go
+++ b/server/websocket_test.go
@@ -24,6 +24,7 @@ import (
 	"errors"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"math/rand"
 	"net"
 	"net/http"
@@ -2013,7 +2014,7 @@ func testWSReadFrame(t testing.TB, br *bufio.Reader) []byte {
 	buf = append(buf, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff)
 	dbr := bytes.NewBuffer(buf)
 	d := flate.NewReader(dbr)
-	uncompressed, err := io.ReadAll(d)
+	uncompressed, err := ioutil.ReadAll(d)
 	if err != nil {
 		t.Fatalf("Error reading frame: %v", err)
 	}
@@ -3126,7 +3127,7 @@ func TestWSCompressionFrameSizeLimit(t *testing.T) {
 			buf = append(buf, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff)
 			dbr := bytes.NewBuffer(buf)
 			d := flate.NewReader(dbr)
-			uncompressed, err := io.ReadAll(d)
+			uncompressed, err := ioutil.ReadAll(d)
 			if err != nil {
 				t.Fatalf("Error reading frame: %v", err)
 			}
diff --git a/test/client_auth_test.go b/test/client_auth_test.go
index a5185a99..80db5d7b 100644
--- a/test/client_auth_test.go
+++ b/test/client_auth_test.go
@@ -15,7 +15,7 @@ package test
 
 import (
 	"fmt"
-	"os"
+	"io/ioutil"
 	"testing"
 
 	"github.com/nats-io/nats.go"
@@ -73,7 +73,7 @@ func TestTokenInConfig(t *testing.T) {
 		token: ` + testToken + `
 		timeout: 5
 	}`
-	if err := os.WriteFile(confFileName, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(confFileName, []byte(content), 0666); err != nil {
 		t.Fatalf("Error writing config file: %v", err)
 	}
 	s, opts := RunServerWithConfig(confFileName)
diff --git a/test/cluster_tls_test.go b/test/cluster_tls_test.go
index b5ab06a1..b19c46ee 100644
--- a/test/cluster_tls_test.go
+++ b/test/cluster_tls_test.go
@@ -15,7 +15,7 @@ package test
 
 import (
 	"fmt"
-	"os"
+	"io/ioutil"
 	"strings"
 	"testing"
 	"time"
@@ -151,7 +151,7 @@ func TestClusterTLSInsecure(t *testing.T) {
 	srvB.SetLogger(wl, false, false)
 
 	// Need to add "insecure: true" and reload
-	if err := os.WriteFile(confB,
+	if err := ioutil.WriteFile(confB,
 		[]byte(fmt.Sprintf(bConfigTemplate, "insecure: true", optsA.Cluster.Host, optsA.Cluster.Port)),
 		0666); err != nil {
 		t.Fatalf("Error rewriting file: %v", err)
diff --git a/test/leafnode_test.go b/test/leafnode_test.go
index 688007c9..b0b1c8b5 100644
--- a/test/leafnode_test.go
+++ b/test/leafnode_test.go
@@ -19,6 +19,7 @@ import (
 	"crypto/x509"
 	"encoding/json"
 	"fmt"
+	"io/ioutil"
 	"math/rand"
 	"net"
 	"net/url"
@@ -3593,7 +3594,7 @@ func TestClusterTLSMixedIPAndDNS(t *testing.T) {
 	remote := &server.RemoteLeafOpts{URLs: []*url.URL{rurl}}
 	remote.TLSConfig = &tls.Config{MinVersion: tls.VersionTLS12}
 	pool := x509.NewCertPool()
-	rootPEM, err := os.ReadFile("./configs/certs/ca.pem")
+	rootPEM, err := ioutil.ReadFile("./configs/certs/ca.pem")
 	if err != nil || rootPEM == nil {
 		t.Fatalf("Error loading or parsing rootCA file: %v", err)
 	}
diff --git a/test/monitor_test.go b/test/monitor_test.go
index 91d2f4f0..d103b68c 100644
--- a/test/monitor_test.go
+++ b/test/monitor_test.go
@@ -18,10 +18,9 @@ import (
 	"crypto/x509"
 	"encoding/json"
 	"fmt"
-	"io"
+	"io/ioutil"
 	"net"
 	"net/http"
-	"os"
 	"strings"
 	"sync"
 	"sync/atomic"
@@ -179,7 +178,7 @@ func TestVarz(t *testing.T) {
 		t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode)
 	}
 	defer resp.Body.Close()
-	body, err := io.ReadAll(resp.Body)
+	body, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		t.Fatalf("Got an error reading the body: %v\n", err)
 	}
@@ -205,7 +204,7 @@ func TestVarz(t *testing.T) {
 		t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode)
 	}
 	defer resp.Body.Close()
-	body, err = io.ReadAll(resp.Body)
+	body, err = ioutil.ReadAll(resp.Body)
 	if err != nil {
 		t.Fatalf("Got an error reading the body: %v\n", err)
 	}
@@ -257,7 +256,7 @@ func TestConnz(t *testing.T) {
 		t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode)
 	}
 	defer resp.Body.Close()
-	body, err := io.ReadAll(resp.Body)
+	body, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		t.Fatalf("Got an error reading the body: %v\n", err)
 	}
@@ -289,7 +288,7 @@ func TestConnz(t *testing.T) {
 		t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode)
 	}
 	defer resp.Body.Close()
-	body, err = io.ReadAll(resp.Body)
+	body, err = ioutil.ReadAll(resp.Body)
 	if err != nil {
 		t.Fatalf("Got an error reading the body: %v\n", err)
 	}
@@ -371,7 +370,7 @@ func TestTLSConnz(t *testing.T) {
 
 	url := fmt.Sprintf("https://127.0.0.1:%d/", opts.HTTPSPort)
 	tlsConfig := &tls.Config{}
-	caCert, err := os.ReadFile(rootCAFile)
+	caCert, err := ioutil.ReadFile(rootCAFile)
 	if err != nil {
 		t.Fatalf("Got error reading RootCA file: %s", err)
 	}
@@ -395,7 +394,7 @@ func TestTLSConnz(t *testing.T) {
 		t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode)
 	}
 	defer resp.Body.Close()
-	body, err := io.ReadAll(resp.Body)
+	body, err := ioutil.ReadAll(resp.Body)
 
 	if err != nil {
 		t.Fatalf("Got an error reading the body: %v\n", err)
@@ -478,7 +477,7 @@ func TestConnzWithSubs(t *testing.T) {
 		t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode)
 	}
 	defer resp.Body.Close()
-	body, err := io.ReadAll(resp.Body)
+	body, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		t.Fatalf("Got an error reading the body: %v\n", err)
 	}
@@ -524,7 +523,7 @@ func TestConnzWithAuth(t *testing.T) {
 		t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode)
 	}
 	defer resp.Body.Close()
-	body, err := io.ReadAll(resp.Body)
+	body, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		t.Fatalf("Got an error reading the body: %v\n", err)
 	}
@@ -585,7 +584,7 @@ func TestConnzWithAccounts(t *testing.T) {
 			t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode)
 		}
 		defer resp.Body.Close()
-		body, err := io.ReadAll(resp.Body)
+		body, err := ioutil.ReadAll(resp.Body)
 		if err != nil {
 			t.Fatalf("Got an error reading the body: %v\n", err)
 		}
@@ -703,7 +702,7 @@ func TestConnzWithOffsetAndLimit(t *testing.T) {
 		t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode)
 	}
 	defer resp.Body.Close()
-	body, err := io.ReadAll(resp.Body)
+	body, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		t.Fatalf("Got an error reading the body: %v\n", err)
 	}
@@ -742,7 +741,7 @@ func TestSubsz(t *testing.T) {
 		t.Fatalf("Expected a 200 response, got %d\n", resp.StatusCode)
 	}
 	defer resp.Body.Close()
-	body, err := io.ReadAll(resp.Body)
+	body, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		t.Fatalf("Got an error reading the body: %v\n", err)
 	}
diff --git a/test/norace_test.go b/test/norace_test.go
index 07b17fec..b26dc266 100644
--- a/test/norace_test.go
+++ b/test/norace_test.go
@@ -20,10 +20,10 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
+	"io/ioutil"
 	"math/rand"
 	"net"
 	"net/url"
-	"os"
 	"regexp"
 	"runtime"
 	"strconv"
@@ -103,7 +103,7 @@ func TestNoRaceRouteSendSubs(t *testing.T) {
 			"nats://%s:%d"
 		]
 	`, optsA.Cluster.Host, optsA.Cluster.Port)
-	if err := os.WriteFile(cfb, []byte(fmt.Sprintf(template, routes)), 0600); err != nil {
+	if err := ioutil.WriteFile(cfb, []byte(fmt.Sprintf(template, routes)), 0600); err != nil {
 		t.Fatalf("Error rewriting B's config file: %v", err)
 	}
 	if err := srvB.Reload(); err != nil {
@@ -220,7 +220,7 @@ func TestNoRaceRouteSendSubs(t *testing.T) {
 	// Otherwise, on test shutdown the client close
 	// will cause the server to try to send unsubs and
 	// this can delay the test.
-	if err := os.WriteFile(cfb, []byte(fmt.Sprintf(template, "")), 0600); err != nil {
+	if err := ioutil.WriteFile(cfb, []byte(fmt.Sprintf(template, "")), 0600); err != nil {
 		t.Fatalf("Error rewriting B's config file: %v", err)
 	}
 	if err := srvB.Reload(); err != nil {
diff --git a/test/ocsp_test.go b/test/ocsp_test.go
index cb77733c..694dd305 100644
--- a/test/ocsp_test.go
+++ b/test/ocsp_test.go
@@ -22,7 +22,7 @@ import (
 	"encoding/base64"
 	"encoding/pem"
 	"fmt"
-	"io"
+	"io/ioutil"
 	"net/http"
 	"os"
 	"path/filepath"
@@ -641,7 +641,7 @@ func TestOCSPReloadRotateTLSCertWithNoURL(t *testing.T) {
 			timeout: 5
 		}
 	`
-	if err := os.WriteFile(conf, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(conf, []byte(content), 0666); err != nil {
 		t.Fatalf("Error writing config: %v", err)
 	}
 	// Reload show warning because of cert missing OCSP Url so cannot be used
@@ -753,7 +753,7 @@ func TestOCSPReloadRotateTLSCertDisableMustStaple(t *testing.T) {
 	}
 	found := false
 	for _, file := range files {
-		data, err := os.ReadFile(file)
+		data, err := ioutil.ReadFile(file)
 		if err != nil {
 			t.Error(err)
 		}
@@ -779,7 +779,7 @@ func TestOCSPReloadRotateTLSCertDisableMustStaple(t *testing.T) {
 		}
 	`
 	content = fmt.Sprintf(updatedContent, storeDir)
-	if err := os.WriteFile(conf, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(conf, []byte(content), 0666); err != nil {
 		t.Fatalf("Error writing config: %v", err)
 	}
 	if err := s.Reload(); err != nil {
@@ -808,7 +808,7 @@ func TestOCSPReloadRotateTLSCertDisableMustStaple(t *testing.T) {
 
 	// Re-enable OCSP Stapling
 	content = fmt.Sprintf(originalContent, storeDir)
-	if err := os.WriteFile(conf, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(conf, []byte(content), 0666); err != nil {
 		t.Fatalf("Error writing config: %v", err)
 	}
 	if err := s.Reload(); err != nil {
@@ -852,7 +852,7 @@ func TestOCSPReloadRotateTLSCertDisableMustStaple(t *testing.T) {
 	}
 	found = false
 	for _, file := range files {
-		data, err := os.ReadFile(file)
+		data, err := ioutil.ReadFile(file)
 		if err != nil {
 			t.Error(err)
 		}
@@ -938,7 +938,7 @@ func TestOCSPReloadRotateTLSCertEnableMustStaple(t *testing.T) {
 			timeout: 5
 		}
 	`
-	if err := os.WriteFile(conf, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(conf, []byte(content), 0666); err != nil {
 		t.Fatalf("Error writing config: %v", err)
 	}
 	if err := s.Reload(); err != nil {
@@ -1223,7 +1223,7 @@ func TestOCSPCluster(t *testing.T) {
 		}
 	`
 	srvConfA = fmt.Sprintf(srvConfA, storeDirA)
-	if err := os.WriteFile(sconfA, []byte(srvConfA), 0666); err != nil {
+	if err := ioutil.WriteFile(sconfA, []byte(srvConfA), 0666); err != nil {
 		t.Fatalf("Error writing config: %v", err)
 	}
 	if err := srvA.Reload(); err != nil {
@@ -1483,7 +1483,7 @@ func TestOCSPLeaf(t *testing.T) {
 		}
 	`
 	srvConfA = fmt.Sprintf(srvConfA, storeDirA)
-	if err := os.WriteFile(sconfA, []byte(srvConfA), 0666); err != nil {
+	if err := ioutil.WriteFile(sconfA, []byte(srvConfA), 0666); err != nil {
 		t.Fatalf("Error writing config: %v", err)
 	}
 	if err := srvA.Reload(); err != nil {
@@ -1775,7 +1775,7 @@ func TestOCSPGateway(t *testing.T) {
 	`
 
 	srvConfA = fmt.Sprintf(srvConfA, storeDirA)
-	if err := os.WriteFile(sconfA, []byte(srvConfA), 0666); err != nil {
+	if err := ioutil.WriteFile(sconfA, []byte(srvConfA), 0666); err != nil {
 		t.Fatalf("Error writing config: %v", err)
 	}
 	if err := srvA.Reload(); err != nil {
@@ -2240,7 +2240,7 @@ func TestOCSPCustomConfigReloadDisable(t *testing.T) {
 			timeout: 5
 		}
 	`
-	if err := os.WriteFile(conf, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(conf, []byte(content), 0666); err != nil {
 		t.Fatalf("Error writing config: %v", err)
 	}
 	if err := s.Reload(); err != nil {
@@ -2342,7 +2342,7 @@ func TestOCSPCustomConfigReloadEnable(t *testing.T) {
 			timeout: 5
 		}
 	`
-	if err := os.WriteFile(conf, []byte(content), 0666); err != nil {
+	if err := ioutil.WriteFile(conf, []byte(content), 0666); err != nil {
 		t.Fatalf("Error writing config: %v", err)
 	}
 	if err := s.Reload(); err != nil {
@@ -2400,7 +2400,7 @@ func newOCSPResponderDesignated(t *testing.T, issuerCertPEM, respCertPEM, respKe
 
 			fmt.Fprintf(rw, "%s %d", key, n)
 		case "POST":
-			data, err := io.ReadAll(r.Body)
+			data, err := ioutil.ReadAll(r.Body)
 			if err != nil {
 				http.Error(rw, err.Error(), http.StatusBadRequest)
 				return
@@ -2496,7 +2496,7 @@ func setOCSPStatus(t *testing.T, ocspURL, certPEM string, status int) {
 	}
 	defer resp.Body.Close()
 
-	data, err := io.ReadAll(resp.Body)
+	data, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		t.Fatalf("failed to read OCSP HTTP response body: %s", err)
 	}
@@ -2531,7 +2531,7 @@ func parseKeyPEM(t *testing.T, keyPEM string) *rsa.PrivateKey {
 
 func parsePEM(t *testing.T, pemPath string) *pem.Block {
 	t.Helper()
-	data, err := os.ReadFile(pemPath)
+	data, err := ioutil.ReadFile(pemPath)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/test/operator_test.go b/test/operator_test.go
index 200ec245..c094e41e 100644
--- a/test/operator_test.go
+++ b/test/operator_test.go
@@ -16,7 +16,7 @@ package test
 import (
 	"bytes"
 	"fmt"
-	"os"
+	"io/ioutil"
 	"strings"
 	"testing"
 	"time"
@@ -416,12 +416,12 @@ func TestReloadDoesNotWipeAccountsWithOperatorMode(t *testing.T) {
 	s2.Shutdown()
 
 	// Now change config and do reload which will do an auth change.
-	b, err := os.ReadFile(conf)
+	b, err := ioutil.ReadFile(conf)
 	if err != nil {
 		t.Fatal(err)
 	}
 	newConf := bytes.Replace(b, []byte("2.2"), []byte("3.3"), 1)
-	err = os.WriteFile(conf, newConf, 0644)
+	err = ioutil.WriteFile(conf, newConf, 0644)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -505,7 +505,7 @@ func TestReloadDoesUpdateAccountsWithMemoryResolver(t *testing.T) {
 	accJWT2, accKP2 := createAccountForConfig(t)
 	accPub2, _ := accKP2.PublicKey()
 	contents = strings.Replace(fmt.Sprintf(cf, "", sysPub, sysPub, sysJWT, accPub2, accJWT2), "\n\t", "\n", -1)
-	err = os.WriteFile(conf, []byte(contents), 0644)
+	err = ioutil.WriteFile(conf, []byte(contents), 0644)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -580,7 +580,7 @@ func TestReloadFailsWithBadAccountsWithMemoryResolver(t *testing.T) {
 
 	// Now add in bogus account for second item and make sure reload fails.
 	contents = strings.Replace(fmt.Sprintf(cf, "", sysPub, sysPub, sysJWT, "foo", "bar"), "\n\t", "\n", -1)
-	err = os.WriteFile(conf, []byte(contents), 0644)
+	err = ioutil.WriteFile(conf, []byte(contents), 0644)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -594,7 +594,7 @@ func TestReloadFailsWithBadAccountsWithMemoryResolver(t *testing.T) {
 	accPub, _ := accKP.PublicKey()
 
 	contents = strings.Replace(fmt.Sprintf(cf, "", sysPub, sysPub, sysJWT, accPub, accJWT), "\n\t", "\n", -1)
-	err = os.WriteFile(conf, []byte(contents), 0644)
+	err = ioutil.WriteFile(conf, []byte(contents), 0644)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/test/pid_test.go b/test/pid_test.go
index dd714cb3..62f4aa7b 100644
--- a/test/pid_test.go
+++ b/test/pid_test.go
@@ -15,6 +15,7 @@ package test
 
 import (
 	"fmt"
+	"io/ioutil"
 	"os"
 	"testing"
 )
@@ -32,7 +33,7 @@ func TestPidFile(t *testing.T) {
 	s := RunServer(&opts)
 	s.Shutdown()
 
-	buf, err := os.ReadFile(opts.PidFile)
+	buf, err := ioutil.ReadFile(opts.PidFile)
 	if err != nil {
 		t.Fatalf("Could not read pid_file: %v", err)
 	}
diff --git a/test/ports_test.go b/test/ports_test.go
index f58b159f..55c27339 100644
--- a/test/ports_test.go
+++ b/test/ports_test.go
@@ -17,6 +17,7 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strings"
@@ -34,7 +35,7 @@ func waitForFile(path string, dur time.Duration) ([]byte, error) {
 			time.Sleep(25 * time.Millisecond)
 			continue
 		} else {
-			return os.ReadFile(path)
+			return ioutil.ReadFile(path)
 		}
 	}
 	return nil, errors.New("Timeout")
@@ -137,7 +138,7 @@ func TestPortsFileReload(t *testing.T) {
 	`, dirA)
 	config = strings.Replace(config, "\\", "/", -1)
 	confPath := filepath.Join(tempDir, fmt.Sprintf("%d.conf", os.Getpid()))
-	if err := os.WriteFile(confPath, []byte(config), 0666); err != nil {
+	if err := ioutil.WriteFile(confPath, []byte(config), 0666); err != nil {
 		t.Fatalf("Error writing ports file (%s): %v", confPath, err)
 	}
 
@@ -178,7 +179,7 @@ func TestPortsFileReload(t *testing.T) {
 		port: -1
 	`, dirB)
 	config = strings.Replace(config, "\\", "/", -1)
-	if err := os.WriteFile(confPath, []byte(config), 0666); err != nil {
+	if err := ioutil.WriteFile(confPath, []byte(config), 0666); err != nil {
 		t.Fatalf("Error writing ports file (%s): %v", confPath, err)
 	}
 
diff --git a/test/route_discovery_test.go b/test/route_discovery_test.go
index d51d3c23..dde99d81 100644
--- a/test/route_discovery_test.go
+++ b/test/route_discovery_test.go
@@ -17,7 +17,7 @@ import (
 	"bufio"
 	"encoding/json"
 	"fmt"
-	"io"
+	"io/ioutil"
 	"net"
 	"net/http"
 	"runtime"
@@ -528,7 +528,7 @@ func readHTTPRoutez(t *testing.T, url string) *server.Routez {
 	if resp.StatusCode != 200 {
 		stackFatalf(t, "Expected a 200 response, got %d\n", resp.StatusCode)
 	}
-	body, err := io.ReadAll(resp.Body)
+	body, err := ioutil.ReadAll(resp.Body)
 	if err != nil {
 		stackFatalf(t, "Got an error reading the body: %v\n", err)
 	}
diff --git a/test/routes_test.go b/test/routes_test.go
index 856329f9..982ba398 100644
--- a/test/routes_test.go
+++ b/test/routes_test.go
@@ -16,9 +16,8 @@ package test
 import (
 	"encoding/json"
 	"fmt"
-	"io"
+	"io/ioutil"
 	"net"
-	"os"
 	"runtime"
 	"strconv"
 	"sync"
@@ -451,11 +450,11 @@ func TestMultipleRoutesSameId(t *testing.T) {
 	// We should only receive on one route, not both.
 	// Check both manually.
 	route1.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
-	buf, _ := io.ReadAll(route1)
+	buf, _ := ioutil.ReadAll(route1)
 	route1.SetReadDeadline(time.Time{})
 	if len(buf) <= 0 {
 		route2.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
-		buf, _ = io.ReadAll(route2)
+		buf, _ = ioutil.ReadAll(route2)
 		route2.SetReadDeadline(time.Time{})
 		if len(buf) <= 0 {
 			t.Fatal("Expected to get one message on a route, received none.")
@@ -1104,7 +1103,7 @@ func createConfFile(t *testing.T, content []byte) string {
 	conf := createFile(t, "")
 	fName := conf.Name()
 	conf.Close()
-	if err := os.WriteFile(fName, content, 0666); err != nil {
+	if err := ioutil.WriteFile(fName, content, 0666); err != nil {
 		removeFile(t, fName)
 		t.Fatalf("Error writing conf file: %v", err)
 	}
diff --git a/test/service_latency_test.go b/test/service_latency_test.go
index 6da77acd..c2dbc6d3 100644
--- a/test/service_latency_test.go
+++ b/test/service_latency_test.go
@@ -16,9 +16,9 @@ package test
 import (
 	"encoding/json"
 	"fmt"
+	"io/ioutil"
 	"math/rand"
 	"net/http"
-	"os"
 	"path/filepath"
 	"strings"
 	"sync"
@@ -1492,7 +1492,7 @@ func TestServiceLatencyRequestorSharesConfig(t *testing.T) {
 
 		system_account: SYS
 	`)
-	if err := os.WriteFile(conf, newConf, 0600); err != nil {
+	if err := ioutil.WriteFile(conf, newConf, 0600); err != nil {
 		t.Fatalf("Error rewriting server's config file: %v", err)
 	}
 	if err := srv.Reload(); err != nil {
diff --git a/test/test.go b/test/test.go
index b54f988d..1534cf32 100644
--- a/test/test.go
+++ b/test/test.go
@@ -19,6 +19,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"net"
 	"os"
 	"path/filepath"
@@ -643,7 +644,7 @@ func createDir(t *testing.T, prefix string) string {
 	if err := os.MkdirAll(tempRoot, 0700); err != nil {
 		t.Fatal(err)
 	}
-	dir, err := os.MkdirTemp(tempRoot, prefix)
+	dir, err := ioutil.TempDir(tempRoot, prefix)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -660,7 +661,7 @@ func createFile(t *testing.T, prefix string) *os.File {
 
 func createFileAtDir(t *testing.T, dir, prefix string) *os.File {
 	t.Helper()
-	f, err := os.CreateTemp(dir, prefix)
+	f, err := ioutil.TempFile(dir, prefix)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/test/tls_test.go b/test/tls_test.go
index 0e6ec3ac..ac17e722 100644
--- a/test/tls_test.go
+++ b/test/tls_test.go
@@ -19,9 +19,9 @@ import (
 	"crypto/x509"
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"net"
 	"net/url"
-	"os"
 	"strings"
 	"sync"
 	"testing"
@@ -91,7 +91,7 @@ func TestTLSClientCertificate(t *testing.T) {
 	}
 
 	// Load in root CA for server verification
-	rootPEM, err := os.ReadFile("./configs/certs/ca.pem")
+	rootPEM, err := ioutil.ReadFile("./configs/certs/ca.pem")
 	if err != nil || rootPEM == nil {
 		t.Fatalf("failed to read root certificate")
 	}
@@ -1840,7 +1840,7 @@ func TestTLSPinnedCertsClient(t *testing.T) {
 		t.Fatalf("Expected error trying to connect without a certificate in pinned_certs")
 	}
 
-	os.WriteFile(confFileName, []byte(fmt.Sprintf(tmpl, "bf6f821f09fde09451411ba3b42c0f74727d61a974c69fd3cf5257f39c75f0e9")), 0660)
+	ioutil.WriteFile(confFileName, []byte(fmt.Sprintf(tmpl, "bf6f821f09fde09451411ba3b42c0f74727d61a974c69fd3cf5257f39c75f0e9")), 0660)
 	if err := srv.Reload(); err != nil {
 		t.Fatalf("on Reload got %v", err)
 	}
@@ -1963,7 +1963,7 @@ func TestTLSPinnedCertsRoute(t *testing.T) {
 	checkClusterFormed(t, srvSeed, srv)
 
 	// this change will result in the server being and remaining disconnected
-	os.WriteFile(confSrv, []byte(fmt.Sprintf(tmplSrv, o.Cluster.Port, "aaaaaaaa09fde09451411ba3b42c0f74727d61a974c69fd3cf5257f39c75f0e9")), 0660)
+	ioutil.WriteFile(confSrv, []byte(fmt.Sprintf(tmplSrv, o.Cluster.Port, "aaaaaaaa09fde09451411ba3b42c0f74727d61a974c69fd3cf5257f39c75f0e9")), 0660)
 	if err := srv.Reload(); err != nil {
 		t.Fatalf("on Reload got %v", err)
 	}