diff --git a/deploy/compile/perform_compilation.go b/deploy/compile/compilers.go
similarity index 82%
rename from deploy/compile/perform_compilation.go
rename to deploy/compile/compilers.go
index c072513bf058f1822bd11ba93b8c27723cd7a7ef..15976c926c8f0cfa4123235b2d002e4870d7862f 100644
--- a/deploy/compile/perform_compilation.go
+++ b/deploy/compile/compilers.go
@@ -9,6 +9,7 @@ import (
 	"regexp"
 	"strings"
 
+	"github.com/hyperledger/burrow/crypto"
 	log "github.com/sirupsen/logrus"
 )
 
@@ -78,12 +79,7 @@ type ResponseItem struct {
 	Binary     SolidityOutputContract `json:"binary"`
 }
 
-const (
-	AddressLength    = 40
-	RelocationLength = 20
-)
-
-func RequestBinaryLinkage(file string, libraries map[string]string) (*BinaryResponse, error) {
+func LinkFile(file string, libraries map[string]string) (*BinaryResponse, error) {
 	//Create Binary Request, send it off
 	codeB, err := ioutil.ReadFile(file)
 	if err != nil {
@@ -94,6 +90,10 @@ func RequestBinaryLinkage(file string, libraries map[string]string) (*BinaryResp
 	if err != nil {
 		return &BinaryResponse{}, err
 	}
+	return LinkContract(contract, libraries)
+}
+
+func LinkContract(contract SolidityOutputContract, libraries map[string]string) (*BinaryResponse, error) {
 	bin := contract.Evm.Bytecode.Object
 	if !strings.Contains(bin, "_") {
 		return &BinaryResponse{
@@ -102,29 +102,31 @@ func RequestBinaryLinkage(file string, libraries map[string]string) (*BinaryResp
 			Error:  "",
 		}, nil
 	}
-	var links map[string]map[string]struct{ Start, Length int }
-	err = json.Unmarshal(contract.Evm.Bytecode.LinkReferences, &links)
+	var links map[string]map[string][]struct{ Start, Length int }
+	err := json.Unmarshal(contract.Evm.Bytecode.LinkReferences, &links)
 	if err != nil {
 		return &BinaryResponse{}, err
 	}
 	for _, f := range links {
-		for name, relo := range f {
+		for name, relos := range f {
 			addr, ok := libraries[name]
 			if !ok {
 				return &BinaryResponse{}, fmt.Errorf("library %s is not defined", name)
 			}
-			if relo.Length != RelocationLength {
-				return &BinaryResponse{}, fmt.Errorf("linkReference should be %d bytes long, not %d", RelocationLength, relo.Length)
-			}
-			if len(addr) != AddressLength {
-				return &BinaryResponse{}, fmt.Errorf("address %s should be %d character long, not %d", addr, AddressLength, len(addr))
-			}
-			start := relo.Start * 2
-			end := relo.Start*2 + AddressLength
-			if bin[start+1] != '_' || bin[end-1] != '_' {
-				return &BinaryResponse{}, fmt.Errorf("relocation dummy not found at %d in %s ", relo.Start, bin)
+			for _, relo := range relos {
+				if relo.Length != crypto.AddressLength {
+					return &BinaryResponse{}, fmt.Errorf("linkReference should be %d bytes long, not %d", crypto.AddressLength, relo.Length)
+				}
+				if len(addr) != crypto.AddressHexLength {
+					return &BinaryResponse{}, fmt.Errorf("address %s should be %d character long, not %d", addr, crypto.AddressHexLength, len(addr))
+				}
+				start := relo.Start * 2
+				end := relo.Start*2 + crypto.AddressHexLength
+				if bin[start+1] != '_' || bin[end-1] != '_' {
+					return &BinaryResponse{}, fmt.Errorf("relocation dummy not found at %d in %s ", relo.Start, bin)
+				}
+				bin = bin[:start] + addr + bin[end:]
 			}
-			bin = bin[:start] + addr + bin[end:]
 		}
 	}
 
@@ -135,7 +137,7 @@ func RequestBinaryLinkage(file string, libraries map[string]string) (*BinaryResp
 	}, nil
 }
 
-func RequestCompile(file string, optimize bool, libraries map[string]string) (*Response, error) {
+func Compile(file string, optimize bool, libraries map[string]string) (*Response, error) {
 	input := SolidityInput{Language: "Solidity", Sources: make(map[string]SolidityInputSource)}
 
 	input.Sources[file] = SolidityInputSource{Urls: []string{file}}
diff --git a/deploy/compile/compilers_test.go b/deploy/compile/compilers_test.go
index a6f112b2d8e69b698a22d1f5a659517934d12dda..b2277880e567befb874305a3c676026433e4d9d5 100644
--- a/deploy/compile/compilers_test.go
+++ b/deploy/compile/compilers_test.go
@@ -61,7 +61,7 @@ func TestLocalMulti(t *testing.T) {
 		Version: "",
 		Error:   "",
 	}
-	resp, err := RequestCompile("contractImport1.sol", false, make(map[string]string))
+	resp, err := Compile("contractImport1.sol", false, make(map[string]string))
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -108,7 +108,7 @@ func TestLocalSingle(t *testing.T) {
 		Version: "",
 		Error:   "",
 	}
-	resp, err := RequestCompile("simpleContract.sol", false, make(map[string]string))
+	resp, err := Compile("simpleContract.sol", false, make(map[string]string))
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -126,7 +126,7 @@ func TestFaultyContract(t *testing.T) {
 	actualOutput, err := exec.Command("solc", "--combined-json", "bin,abi", "faultyContract.sol").CombinedOutput()
 	err = json.Unmarshal(actualOutput, expectedSolcResponse)
 	t.Log(expectedSolcResponse.Error)
-	resp, err := RequestCompile("faultyContract.sol", false, make(map[string]string))
+	resp, err := Compile("faultyContract.sol", false, make(map[string]string))
 	t.Log(resp.Error)
 	if err != nil {
 		if expectedSolcResponse.Error != resp.Error {
diff --git a/deploy/jobs/job_manager.go b/deploy/jobs/job_manager.go
index f9b2fe927e8a9c64e1927e66d4d494fde770c666..fce69361818cdf831f139d44d8aa3a9fca1a7364 100644
--- a/deploy/jobs/job_manager.go
+++ b/deploy/jobs/job_manager.go
@@ -2,13 +2,28 @@ package jobs
 
 import (
 	"fmt"
+	"path/filepath"
 	"strings"
 
+	compilers "github.com/hyperledger/burrow/deploy/compile"
 	"github.com/hyperledger/burrow/deploy/def"
 	"github.com/hyperledger/burrow/deploy/util"
 	log "github.com/sirupsen/logrus"
 )
 
+type trackJob struct {
+	payload      def.Payload
+	job          *def.Job
+	compilerResp *compilers.Response
+	err          error
+	done         chan struct{}
+}
+
+func compile(contract string, track *trackJob) {
+	(*track).compilerResp, (*track).err = compilers.Compile(contract, false, nil)
+	close(track.done)
+}
+
 func RunJobs(do *def.Packages) error {
 
 	// Dial the chain if needed
@@ -40,21 +55,51 @@ func RunJobs(do *def.Packages) error {
 		return fmt.Errorf("error validating Burrow deploy file at %s: %v", do.YAMLPath, err)
 	}
 
+	intermediateJobs := make([]*trackJob, 0, len(do.Package.Jobs))
+
 	for _, job := range do.Package.Jobs {
 		payload, err := job.Payload()
 		if err != nil {
 			return fmt.Errorf("could not get Job payload: %v", payload)
 		}
-		err = util.PreProcessFields(payload, do)
+
+		track := trackJob{job: job, payload: payload}
+		intermediateJobs = append(intermediateJobs, &track)
+
+		// Do compilation first
+		switch payload.(type) {
+		case *def.Build:
+			track.done = make(chan struct{})
+			go compile(job.Build.Contract, &track)
+		case *def.Deploy:
+			if filepath.Ext(job.Deploy.Contract) == ".sol" {
+				track.done = make(chan struct{})
+				go compile(job.Deploy.Contract, &track)
+			}
+		}
+	}
+
+	for _, m := range intermediateJobs {
+		job := m.job
+
+		err = util.PreProcessFields(m.payload, do)
 		if err != nil {
 			return err
 		}
 		// Revalidate with possible replacements
-		err = payload.Validate()
+		err = m.payload.Validate()
 		if err != nil {
 			return fmt.Errorf("error validating job %s after pre-processing variables: %v", job.Name, err)
 		}
-		switch payload.(type) {
+
+		if m.done != nil {
+			<-m.done
+			if m.err != nil {
+				return m.err
+			}
+		}
+
+		switch m.payload.(type) {
 		// Meta Job
 		case *def.Meta:
 			announce(job.Name, "Meta")
@@ -88,13 +133,13 @@ func RunJobs(do *def.Packages) error {
 		// Contracts jobs
 		case *def.Deploy:
 			announce(job.Name, "Deploy")
-			job.Result, err = DeployJob(job.Deploy, do)
+			job.Result, err = DeployJob(job.Deploy, do, m.compilerResp)
 		case *def.Call:
 			announce(job.Name, "Call")
 			job.Result, job.Variables, err = CallJob(job.Call, do)
 		case *def.Build:
 			announce(job.Name, "Build")
-			job.Result, err = BuildJob(job.Build, do)
+			job.Result, err = BuildJob(job.Build, do, m.compilerResp)
 
 		// State jobs
 		case *def.RestoreState:
@@ -222,6 +267,9 @@ func burrowConnectionNeeded(do *def.Packages) (error, bool) {
 			return fmt.Errorf("could not get Job payload: %v", payload), false
 		}
 		switch payload.(type) {
+		case *def.Meta:
+			// A meta jobs will call runJobs again, so it does not need a connection for itself
+			continue
 		case *def.Build:
 			continue
 		case *def.Set:
diff --git a/deploy/jobs/jobs_contracts.go b/deploy/jobs/jobs_contracts.go
index ce6427418cf1519e83556318d67843862b8131af..62c6c57c367d7cd64b2705e0d7c03926b166ef6d 100644
--- a/deploy/jobs/jobs_contracts.go
+++ b/deploy/jobs/jobs_contracts.go
@@ -18,7 +18,7 @@ import (
 	log "github.com/sirupsen/logrus"
 )
 
-func BuildJob(build *def.Build, do *def.Packages) (result string, err error) {
+func BuildJob(build *def.Build, do *def.Packages, resp *compilers.Response) (result string, err error) {
 	// assemble contract
 	contractPath, err := findContractFile(build.Contract, do.BinPath)
 	if err != nil {
@@ -28,10 +28,9 @@ func BuildJob(build *def.Build, do *def.Packages) (result string, err error) {
 	log.WithField("=>", contractPath).Info("Contract path")
 
 	// normal compilation/deploy sequence
-	resp, err := compilers.RequestCompile(contractPath, false, make(map[string]string))
-	if err != nil {
-		log.Errorln("Error compiling contracts: Compilers error:")
-		return "", err
+	if resp == nil {
+		log.Errorln("Error compiling contracts: Missing compiler result")
+		return "", fmt.Errorf("internal error")
 	} else if resp.Error != "" {
 		log.Errorln("Error compiling contracts: Language error:")
 		return "", fmt.Errorf("%v", resp.Error)
@@ -78,7 +77,7 @@ func BuildJob(build *def.Build, do *def.Packages) (result string, err error) {
 	return "", nil
 }
 
-func DeployJob(deploy *def.Deploy, do *def.Packages) (result string, err error) {
+func DeployJob(deploy *def.Deploy, do *def.Packages, resp *compilers.Response) (result string, err error) {
 	deploy.Libraries, _ = util.PreProcessLibs(deploy.Libraries, do)
 	// trim the extension
 	contractName := strings.TrimSuffix(deploy.Contract, filepath.Ext(deploy.Contract))
@@ -118,7 +117,7 @@ func DeployJob(deploy *def.Deploy, do *def.Packages) (result string, err error)
 		log.Info("Binary file detected. Using binary deploy sequence.")
 		log.WithField("=>", contractPath).Info("Binary path")
 
-		binaryResponse, err := compilers.RequestBinaryLinkage(contractPath, libs)
+		binaryResponse, err := compilers.LinkFile(contractPath, libs)
 		if err != nil {
 			return "", fmt.Errorf("Something went wrong with your binary deployment: %v", err)
 		}
@@ -153,11 +152,10 @@ func DeployJob(deploy *def.Deploy, do *def.Packages) (result string, err error)
 		contractPath = deploy.Contract
 		log.WithField("=>", contractPath).Info("Contract path")
 		// normal compilation/deploy sequence
-		resp, err := compilers.RequestCompile(contractPath, false, libs)
 
-		if err != nil {
-			log.Errorln("Error compiling contracts: Compilers error:")
-			return "", err
+		if resp == nil {
+			log.Errorln("Error compiling contracts: Missing compiler result")
+			return "", fmt.Errorf("internal error")
 		} else if resp.Error != "" {
 			log.Errorln("Error compiling contracts: Language error:")
 			return "", fmt.Errorf("%v", resp.Error)
@@ -172,7 +170,7 @@ func DeployJob(deploy *def.Deploy, do *def.Packages) (result string, err error)
 			log.WithField("=>", string(response.Binary.Abi)).Info("Abi")
 			log.WithField("=>", response.Binary.Evm.Bytecode.Object).Info("Bin")
 			if response.Binary.Evm.Bytecode.Object != "" {
-				result, err = deployContract(deploy, do, response)
+				result, err = deployContract(deploy, do, response, libs)
 				if err != nil {
 					return "", err
 				}
@@ -184,7 +182,7 @@ func DeployJob(deploy *def.Deploy, do *def.Packages) (result string, err error)
 				if response.Binary.Evm.Bytecode.Object == "" {
 					continue
 				}
-				result, err = deployContract(deploy, do, response)
+				result, err = deployContract(deploy, do, response, libs)
 				if err != nil {
 					return "", err
 				}
@@ -205,7 +203,7 @@ func DeployJob(deploy *def.Deploy, do *def.Packages) (result string, err error)
 				if matchInstanceName(response.Objectname, deploy.Instance) {
 					log.WithField("=>", string(response.Binary.Abi)).Info("Abi")
 					log.WithField("=>", response.Binary.Evm.Bytecode.Object).Info("Bin")
-					result, err = deployContract(deploy, do, response)
+					result, err = deployContract(deploy, do, response, libs)
 					if err != nil {
 						return "", err
 					}
@@ -241,9 +239,14 @@ func findContractFile(contract, binPath string) (string, error) {
 }
 
 // TODO [rj] refactor to remove [contractPath] from functions signature => only used in a single error throw.
-func deployContract(deploy *def.Deploy, do *def.Packages, compilersResponse compilers.ResponseItem) (string, error) {
+func deployContract(deploy *def.Deploy, do *def.Packages, compilersResponse compilers.ResponseItem, libs map[string]string) (string, error) {
 	log.WithField("=>", string(compilersResponse.Binary.Abi)).Debug("Specification (From Compilers)")
-	contractCode := compilersResponse.Binary.Evm.Bytecode.Object
+
+	linked, err := compilers.LinkContract(compilersResponse.Binary, libs)
+	if err != nil {
+		return "", err
+	}
+	contractCode := linked.Binary
 
 	// Save
 	if _, err := os.Stat(do.BinPath); os.IsNotExist(err) {