format response
diff --git a/api.go b/api.go
index 5f61078..5054d98 100644
--- a/api.go
+++ b/api.go
@@ -1,3 +1,16 @@
+// Copyright 2017 Google Inc.
+//
+// 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.
 package apiGatewayConfDeploy
 
 import (
@@ -31,6 +44,7 @@
 	sqlTimeFormat    = "2006-01-02 15:04:05.999 -0700 MST"
 	iso8601          = "2006-01-02T15:04:05.999Z07:00"
 	sqliteTimeFormat = "2006-01-02 15:04:05.999-07:00"
+	changeTimeFormat = "2006-01-02 15:04:05.999"
 )
 
 type deploymentsResult struct {
@@ -54,27 +68,29 @@
 type ApiDeploymentDetails struct {
 	Self           string `json:"self"`
 	Name           string `json:"name"`
-	Org            string `json:"org"`
-	Env            string `json:"env"`
 	Type           string `json:"type"`
-	BlobURL        string `json:"bloburl"`
+	Org            string `json:"organization"`
+	Env            string `json:"environment"`
+	Scope          string `json:"scope"`
 	Revision       string `json:"revision"`
 	BlobId         string `json:"blobId"`
+	BlobURL        string `json:"bloburl"`
 	ResourceBlobId string `json:"resourceBlobId"`
 	Created        string `json:"created"`
 	Updated        string `json:"updated"`
 }
 
 type ApiDeploymentResponse struct {
-	Kind                  string                 `json:"kind"`
-	Self                  string                 `json:"self"`
-	ApiDeploymentResponse []ApiDeploymentDetails `json:"contents"`
+	Kind                   string                 `json:"kind"`
+	Self                   string                 `json:"self"`
+	ApiDeploymentsResponse []ApiDeploymentDetails `json:"contents"`
 }
 
 const deploymentsEndpoint = "/configurations"
 const BlobEndpoint = "/blob/{blobId}"
 
 func InitAPI() {
+	log.Debug("API endpoints initialized")
 	services.API().HandleFunc(deploymentsEndpoint, apiGetCurrentDeployments).Methods("GET")
 	services.API().HandleFunc(BlobEndpoint, apiReturnBlobData).Methods("GET")
 }
@@ -126,7 +142,7 @@
 }
 
 func distributeEvents() {
-	subscribers := make(map[chan deploymentsResult]struct{})
+	subscribers := make(map[chan deploymentsResult]bool)
 	deliverDeployments := make(chan []interface{}, 1)
 
 	go debounce(deploymentsChanged, deliverDeployments, debounceDuration)
@@ -138,10 +154,10 @@
 				return // todo: using this?
 			}
 			subs := subscribers
-			subscribers = make(map[chan deploymentsResult]struct{})
+			subscribers = make(map[chan deploymentsResult]bool)
 			go func() {
 				eTag := incrementETag()
-				deployments, err := getUnreadyDeployments()
+				deployments, err := dbMan.getUnreadyDeployments()
 				log.Debugf("delivering deployments to %d subscribers", len(subs))
 				for subscriber := range subs {
 					log.Debugf("delivering to: %v", subscriber)
@@ -150,7 +166,7 @@
 			}()
 		case subscriber := <-addSubscriber:
 			log.Debugf("Add subscriber: %v", subscriber)
-			subscribers[subscriber] = struct{}{}
+			subscribers[subscriber] = true
 		case subscriber := <-removeSubscriber:
 			log.Debugf("Remove subscriber: %v", subscriber)
 			delete(subscribers, subscriber)
@@ -162,7 +178,7 @@
 
 	vars := mux.Vars(r)
 	blobId := vars["blobId"]
-	fs, err := getLocalFSLocation(blobId)
+	fs, err := dbMan.getLocalFSLocation(blobId)
 	if err != nil {
 		writeInternalError(w, "BlobId "+blobId+" has no mapping blob file")
 		return
@@ -248,7 +264,7 @@
 
 func sendReadyDeployments(w http.ResponseWriter) {
 	eTag := getETag()
-	deployments, err := getReadyDeployments()
+	deployments, err := dbMan.getReadyDeployments()
 	if err != nil {
 		writeInternalError(w, "Database error")
 		return
@@ -256,7 +272,7 @@
 	sendDeployments(w, deployments, eTag)
 }
 
-func get_http_host() string {
+func getHttpHost() string {
 	// apid-core has to set this according to the protocol apid is to be run: http/https
 	proto := config.GetString("protocol_type")
 	if proto == "" {
@@ -269,25 +285,28 @@
 func sendDeployments(w http.ResponseWriter, dataDeps []DataDeployment, eTag string) {
 
 	apiDeps := ApiDeploymentResponse{}
-	apiDepDetails := []ApiDeploymentDetails{}
+	apiDepDetails := make([]ApiDeploymentDetails, 0)
 
 	apiDeps.Kind = "Collections"
-	apiDeps.Self = get_http_host() + "/configurations"
+	apiDeps.Self = getHttpHost() + "/configurations"
 
 	for _, d := range dataDeps {
 		apiDepDetails = append(apiDepDetails, ApiDeploymentDetails{
+			Self:           apiDeps.Self + "/" + d.ID,
+			Name:		d.Name,
+			Type:           d.Type,
 			Org:            d.OrgID,
 			Env:            d.EnvID,
+			Scope:          getDeploymentScope(),
 			Revision:       d.Revision,
 			BlobId:         d.GWBlobID,
-			ResourceBlobId: d.BlobResourceID,
-			Created:        d.Created,
-			Updated:        d.Updated,
-			Type:           d.Type,
 			BlobURL:        d.BlobURL,
+			ResourceBlobId: d.BlobResourceID,
+			Created:        convertTime(d.Created),
+			Updated:        convertTime(d.Updated),
 		})
 	}
-	apiDeps.ApiDeploymentResponse = apiDepDetails
+	apiDeps.ApiDeploymentsResponse = apiDepDetails
 
 	b, err := json.Marshal(apiDeps)
 	if err != nil {
@@ -311,3 +330,24 @@
 	e := atomic.LoadInt64(&eTag)
 	return strconv.FormatInt(e, 10)
 }
+
+// TODO
+func getDeploymentScope() string{
+	return ""
+}
+
+func convertTime(t string) string {
+	if t == "" {
+		return ""
+	}
+	formats := []string{sqliteTimeFormat, sqlTimeFormat, iso8601, time.RFC3339, changeTimeFormat}
+	for _, f := range formats {
+		timestamp, err := time.Parse(f, t)
+		if err == nil {
+			return timestamp.Format(iso8601)
+		}
+	}
+	log.Error("convertTime: Unsupported time format: " + t)
+	return t
+}
+
diff --git a/api_test.go b/api_test.go
new file mode 100644
index 0000000..fba8e0c
--- /dev/null
+++ b/api_test.go
@@ -0,0 +1,237 @@
+// Copyright 2017 Google Inc.
+//
+// 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.
+package apiGatewayConfDeploy
+import (
+	"encoding/json"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+
+
+
+
+var _ = Describe("api", func() {
+	Context("GET /deployments", func() {
+
+		It("should get empty set if no deployments", func() {
+
+			uri, err := url.Parse(apiServerBaseURI)
+			Expect(err).Should(Succeed())
+			uri.Path = deploymentsEndpoint
+			res, err := http.Get(uri.String())
+			Expect(err).Should(Succeed())
+			defer res.Body.Close()
+
+			Expect(res.StatusCode).Should(Equal(http.StatusOK))
+
+			var depRes ApiDeploymentResponse
+			body, err := ioutil.ReadAll(res.Body)
+			Expect(err).ShouldNot(HaveOccurred())
+			json.Unmarshal(body, &depRes)
+
+			log.Error(depRes)
+
+			//Expect(len(depRes)).To(Equal(0))
+			//Expect(string(body)).Should(Equal("[]"))
+		})
+		/*
+		It("should debounce requests", func(done Done) {
+			var in = make(chan interface{})
+			var out = make(chan []interface{})
+
+			go debounce(in, out, 3*time.Millisecond)
+
+			go func() {
+				defer GinkgoRecover()
+
+				received, ok := <-out
+				Expect(ok).To(BeTrue())
+				Expect(len(received)).To(Equal(2))
+
+				close(in)
+				received, ok = <-out
+				Expect(ok).To(BeFalse())
+
+				close(done)
+			}()
+
+			in <- "x"
+			in <- "y"
+		})
+
+		It("should get current deployments", func() {
+
+			deploymentID := "api_get_current"
+			insertTestDeployment(testServer, deploymentID)
+
+			uri, err := url.Parse(testServer.URL)
+			uri.Path = deploymentsEndpoint
+
+			res, err := http.Get(uri.String())
+			Expect(err).ShouldNot(HaveOccurred())
+			defer res.Body.Close()
+
+			Expect(res.StatusCode).Should(Equal(http.StatusOK))
+
+			var depRes ApiDeploymentResponse
+			body, err := ioutil.ReadAll(res.Body)
+			Expect(err).ShouldNot(HaveOccurred())
+			json.Unmarshal(body, &depRes)
+
+			Expect(len(depRes)).To(Equal(1))
+
+			dep := depRes[0]
+
+			Expect(dep.ID).To(Equal(deploymentID))
+			Expect(dep.ScopeId).To(Equal(deploymentID))
+			Expect(dep.DisplayName).To(Equal(deploymentID))
+
+			var config bundleConfigJson
+
+			err = json.Unmarshal(dep.ConfigJson, &config)
+			Expect(err).ShouldNot(HaveOccurred())
+			Expect(config.Name).To(Equal("/bundles/1"))
+
+			err = json.Unmarshal(dep.BundleConfigJson, &config)
+			Expect(err).ShouldNot(HaveOccurred())
+			Expect(config.Name).To(Equal("/bundles/1"))
+		})
+
+		It("should get 304 for no change", func() {
+
+			deploymentID := "api_no_change"
+			insertTestDeployment(testServer, deploymentID)
+
+			uri, err := url.Parse(testServer.URL)
+			uri.Path = deploymentsEndpoint
+			res, err := http.Get(uri.String())
+			Expect(err).ShouldNot(HaveOccurred())
+			defer res.Body.Close()
+			Expect(res.Header.Get("etag")).ShouldNot(BeEmpty())
+
+			req, err := http.NewRequest("GET", uri.String(), nil)
+			req.Header.Add("Content-Type", "application/json")
+			req.Header.Add("If-None-Match", res.Header.Get("etag"))
+
+			res, err = http.DefaultClient.Do(req)
+			Expect(err).ShouldNot(HaveOccurred())
+			defer res.Body.Close()
+			Expect(res.StatusCode).To(Equal(http.StatusNotModified))
+		})
+
+		It("should get empty set after blocking if no deployments", func() {
+
+			uri, err := url.Parse(testServer.URL)
+			uri.Path = deploymentsEndpoint
+
+			query := uri.Query()
+			query.Add("block", "1")
+			uri.RawQuery = query.Encode()
+
+			res, err := http.Get(uri.String())
+			Expect(err).ShouldNot(HaveOccurred())
+			defer res.Body.Close()
+
+			var depRes ApiDeploymentResponse
+			body, err := ioutil.ReadAll(res.Body)
+			Expect(err).ShouldNot(HaveOccurred())
+			json.Unmarshal(body, &depRes)
+
+			Expect(res.StatusCode).Should(Equal(http.StatusOK))
+			Expect(string(body)).Should(Equal("[]"))
+		})
+
+		It("should get new deployment set after blocking", func(done Done) {
+
+			deploymentID := "api_get_current_blocking"
+			insertTestDeployment(testServer, deploymentID)
+			uri, err := url.Parse(testServer.URL)
+			uri.Path = deploymentsEndpoint
+			res, err := http.Get(uri.String())
+			Expect(err).ShouldNot(HaveOccurred())
+			defer res.Body.Close()
+			eTag := res.Header.Get("etag")
+			Expect(eTag).ShouldNot(BeEmpty())
+
+			deploymentID = "api_get_current_blocking2"
+			go func() {
+				defer GinkgoRecover()
+
+				query := uri.Query()
+				query.Add("block", "1")
+				uri.RawQuery = query.Encode()
+				req, err := http.NewRequest("GET", uri.String(), nil)
+				req.Header.Add("Content-Type", "application/json")
+				req.Header.Add("If-None-Match", eTag)
+
+				res, err := http.DefaultClient.Do(req)
+				Expect(err).ShouldNot(HaveOccurred())
+				defer res.Body.Close()
+				Expect(res.StatusCode).To(Equal(http.StatusOK))
+
+				Expect(res.Header.Get("etag")).ShouldNot(BeEmpty())
+				Expect(res.Header.Get("etag")).ShouldNot(Equal(eTag))
+
+				var depRes ApiDeploymentResponse
+				body, err := ioutil.ReadAll(res.Body)
+				Expect(err).ShouldNot(HaveOccurred())
+				json.Unmarshal(body, &depRes)
+
+				Expect(len(depRes)).To(Equal(2))
+
+				dep := depRes[1]
+
+				Expect(dep.ID).To(Equal(deploymentID))
+				Expect(dep.ScopeId).To(Equal(deploymentID))
+				Expect(dep.DisplayName).To(Equal(deploymentID))
+
+				close(done)
+			}()
+
+			time.Sleep(250 * time.Millisecond) // give api call above time to block
+			insertTestDeployment(testServer, deploymentID)
+			deploymentsChanged <- deploymentID
+		})
+
+		It("should get 304 after blocking if no new deployment", func() {
+
+			deploymentID := "api_no_change_blocking"
+			insertTestDeployment(testServer, deploymentID)
+			uri, err := url.Parse(testServer.URL)
+			uri.Path = deploymentsEndpoint
+			res, err := http.Get(uri.String())
+			Expect(err).ShouldNot(HaveOccurred())
+			defer res.Body.Close()
+			Expect(res.Header.Get("etag")).ShouldNot(BeEmpty())
+
+			query := uri.Query()
+			query.Add("block", "1")
+			uri.RawQuery = query.Encode()
+			req, err := http.NewRequest("GET", uri.String(), nil)
+			req.Header.Add("Content-Type", "application/json")
+			req.Header.Add("If-None-Match", res.Header.Get("etag"))
+
+			res, err = http.DefaultClient.Do(req)
+			Expect(err).ShouldNot(HaveOccurred())
+			defer res.Body.Close()
+			Expect(res.StatusCode).To(Equal(http.StatusNotModified))
+		})
+		*/
+	})
+})
\ No newline at end of file
diff --git a/apidGatewayConfDeploy_suite_test.go b/apidGatewayConfDeploy_suite_test.go
new file mode 100644
index 0000000..9cc294a
--- /dev/null
+++ b/apidGatewayConfDeploy_suite_test.go
@@ -0,0 +1,46 @@
+package apiGatewayConfDeploy
+
+import (
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+	"github.com/30x/apid-core"
+	"github.com/30x/apid-core/factory"
+	"io/ioutil"
+	"net/http/httptest"
+	"time"
+	"os"
+	"net/url"
+)
+
+
+var (
+	tmpDir              string
+)
+
+var _ = BeforeSuite(func() {
+	apid.Initialize(factory.DefaultServicesFactory())
+	config := apid.Config()
+	var err error
+	tmpDir, err = ioutil.TempDir("", "api_test")
+	Expect(err).NotTo(HaveOccurred())
+
+	config.Set("local_storage_path", tmpDir)
+	config.Set(configApidInstanceID, "INSTANCE_ID")
+	config.Set(configApidClusterID, "CLUSTER_ID")
+	config.Set(configApiServerBaseURI, "http://localhost")
+	config.Set(configDebounceDuration, "1ms")
+	apid.InitializePlugins("")
+
+
+	bundleCleanupDelay = time.Millisecond
+	bundleRetryDelay = 10 * time.Millisecond
+	markDeploymentFailedAfter = 50 * time.Millisecond
+	concurrentDownloads = 1
+	downloadQueueSize = 1
+
+})
+
+var _ = AfterSuite(func() {
+	apid.Events().Close()
+	os.RemoveAll(tmpDir)
+})
\ No newline at end of file
diff --git a/bundle.go b/bundle.go
index 0378f30..ee36cbb 100644
--- a/bundle.go
+++ b/bundle.go
@@ -1,3 +1,16 @@
+// Copyright 2017 Google Inc.
+//
+// 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.
 package apiGatewayConfDeploy
 
 import (
@@ -82,7 +95,7 @@
 	if err == nil {
 		blobId := atomic.AddInt64(&gwBlobId, 1)
 		blobIds := strconv.FormatInt(blobId, 10)
-		err = updatelocal_fs_location(dep.ID, blobIds, r.bundleFile)
+		err = dbMan.updateLocalFsLocation(dep.ID, blobIds, r.bundleFile)
 		if err != nil {
 			dep.GWBlobID = blobIds
 		}
diff --git a/data.go b/data.go
index a867e7a..3ec5eca 100644
--- a/data.go
+++ b/data.go
@@ -1,3 +1,16 @@
+// Copyright 2017 Google Inc.
+//
+// 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.
 package apiGatewayConfDeploy
 
 import (
@@ -8,8 +21,7 @@
 )
 
 var (
-	unsafeDB apid.DB
-	dbMux    sync.RWMutex
+	dbMan dbManagerInterface
 	gwBlobId int64
 )
 
@@ -35,8 +47,41 @@
 	Exec(query string, args ...interface{}) (sql.Result, error)
 }
 
-func InitDB(db apid.DB) error {
-	_, err := db.Exec(`
+
+type dbManagerInterface interface {
+	setDbVersion(string)
+	initDb() error
+	getUnreadyDeployments() ([]DataDeployment, error)
+	getReadyDeployments() ([]DataDeployment, error)
+	updateLocalFsLocation(string, string, string) error
+	getLocalFSLocation(string) (string, error)
+}
+
+
+type dbManager struct {
+	data apid.DataService
+	db apid.DB
+	dbMux    sync.RWMutex
+}
+
+func (dbc *dbManager) setDbVersion(version string) {
+	db, err := dbc.data.DBVersion(version)
+	if err != nil {
+		log.Panicf("Unable to access database: %v", err)
+	}
+	dbc.dbMux.Lock()
+	dbc.db = db
+	dbc.dbMux.Unlock()
+}
+
+func (dbc *dbManager) getDb() apid.DB {
+	dbc.dbMux.RLock()
+	defer dbc.dbMux.RUnlock()
+	return dbc.db
+}
+
+func (dbc *dbManager) initDb() error{
+	_, err := dbc.getDb().Exec(`
 	CREATE TABLE IF NOT EXISTS edgex_blob_available (
    		gwblobid integer primary key,
    		runtime_meta_id character varying NOT NULL,
@@ -52,28 +97,11 @@
 	return nil
 }
 
-func getDB() apid.DB {
-	dbMux.RLock()
-	db := unsafeDB
-	dbMux.RUnlock()
-	return db
-}
-
-// caller is responsible for calling dbMux.Lock() and dbMux.Unlock()
-func SetDB(db apid.DB) {
-	if unsafeDB == nil { // init API when DB is initialized
-		go InitAPI()
-	}
-	unsafeDB = db
-}
-
 // getUnreadyDeployments() returns array of resources that are not yet to be processed
-func getUnreadyDeployments() (deployments []DataDeployment, err error) {
+func (dbc *dbManager) getUnreadyDeployments() (deployments []DataDeployment, err error) {
 
-	err = nil
-	db := getDB()
 
-	rows, err := db.Query(`
+	rows, err := dbc.getDb().Query(`
 	SELECT project_runtime_blob_metadata.id, org_id, env_id, name, revision, blob_id, resource_blob_id
 		FROM project_runtime_blob_metadata
 			LEFT JOIN edgex_blob_available
@@ -103,12 +131,10 @@
 }
 
 // getDeployments()
-func getReadyDeployments() (deployments []DataDeployment, err error) {
+func (dbc *dbManager) getReadyDeployments() (deployments []DataDeployment, err error) {
 
-	err = nil
-	db := getDB()
 
-	rows, err := db.Query(`
+	rows, err := dbc.getDb().Query(`
 	SELECT a.id, a.org_id, a.env_id, a.name, a.type, a.revision, a.blob_id,
 		a.resource_blob_id, a.created_at, a.created_by, a.updated_at, a.updated_by,
 		b.local_fs_location, b.access_url, b.gwblobid
@@ -139,10 +165,10 @@
 
 }
 
-func updatelocal_fs_location(depID, bundleId, local_fs_location string) error {
+func (dbc *dbManager) updateLocalFsLocation(depID, bundleId, localFsLocation string) error {
 
-	access_url := get_http_host() + "/blob/" + bundleId
-	stmt, err := getDB().Prepare(`
+	access_url := getHttpHost() + "/blob/" + bundleId
+	stmt, err := dbc.getDb().Prepare(`
 		INSERT INTO edgex_blob_available (runtime_meta_id, gwblobid, local_fs_location, access_url)
 			VALUES (?, ?, ?, ?)`)
 	if err != nil {
@@ -151,22 +177,21 @@
 	}
 	defer stmt.Close()
 
-	_, err = stmt.Exec(depID, bundleId, local_fs_location, access_url)
+	_, err = stmt.Exec(depID, bundleId, localFsLocation, access_url)
 	if err != nil {
-		log.Errorf("UPDATE edgex_blob_available id {%s} local_fs_location {%s} failed: %v", depID, local_fs_location, err)
+		log.Errorf("UPDATE edgex_blob_available id {%s} local_fs_location {%s} failed: %v", depID, localFsLocation, err)
 		return err
 	}
 
-	log.Debugf("INSERT edgex_blob_available {%s} local_fs_location {%s} succeeded", depID, local_fs_location)
+	log.Debugf("INSERT edgex_blob_available {%s} local_fs_location {%s} succeeded", depID, localFsLocation)
 	return nil
 
 }
 
-func getLocalFSLocation(blobId string) (locfs string, err error) {
+func (dbc *dbManager) getLocalFSLocation(blobId string) (locfs string, err error) {
 
-	db := getDB()
 	log.Debugf("Getting the blob file for blobId {%s}", blobId)
-	rows, err := db.Query("SELECT local_fs_location FROM edgex_blob_available WHERE gwblobid = \"" + blobId + "\"")
+	rows, err := dbc.getDb().Query("SELECT local_fs_location FROM edgex_blob_available WHERE gwblobid = \"" + blobId + "\"")
 	if err != nil {
 		log.Errorf("SELECT local_fs_location failed %v", err)
 		return "", err
diff --git a/init.go b/init.go
index 745197f..7c9b530 100644
--- a/init.go
+++ b/init.go
@@ -1,3 +1,16 @@
+// Copyright 2017 Google Inc.
+//
+// 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.
 package apiGatewayConfDeploy
 
 import (
@@ -8,6 +21,7 @@
 	"time"
 
 	"github.com/30x/apid-core"
+	"sync"
 )
 
 const (
@@ -28,7 +42,6 @@
 var (
 	services            apid.Services
 	log                 apid.LogService
-	data                apid.DataService
 	config              apid.ConfigService
 	bundlePath          string
 	debounceDuration    time.Duration
@@ -104,7 +117,11 @@
 		return pluginData, fmt.Errorf("%s must be a positive duration", configDownloadConnTimeout)
 	}
 
-	data = services.Data()
+	dbMan = &dbManager{
+		data: services.Data(),
+		dbMux: sync.RWMutex{},
+	}
+
 	blobServerURL = config.GetString(configBlobServerBaseURI)
 	concurrentDownloads = config.GetInt(configConcurrentDownloads)
 	downloadQueueSize = config.GetInt(configDownloadQueueSize)
diff --git a/listener.go b/listener.go
index 23cc071..d30aabb 100644
--- a/listener.go
+++ b/listener.go
@@ -1,3 +1,16 @@
+// Copyright 2017 Google Inc.
+//
+// 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.
 package apiGatewayConfDeploy
 
 import (
@@ -14,6 +27,8 @@
 	CONFIG_METADATA_TABLE = "project.runtime_blob_metadata"
 )
 
+var apiInitialized bool
+
 func initListener(services apid.Services) {
 	services.Events().Listen(APIGEE_SYNC_EVENT, &apigeeSyncHandler{})
 }
@@ -47,25 +62,19 @@
 
 	log.Debugf("Snapshot received. Switching to DB version: %s", snapshot.SnapshotInfo)
 
-	db, err := data.DBVersion(snapshot.SnapshotInfo)
-	if err != nil {
-		log.Panicf("Unable to access database: %v", err)
-	}
+	dbMan.setDbVersion(snapshot.SnapshotInfo)
 
-	// Update the DB pointer
-	dbMux.Lock()
-	SetDB(db)
-	dbMux.Unlock()
-
-	InitDB(db)
 	startupOnExistingDatabase()
+	if !apiInitialized {
+		InitAPI()
+	}
 	log.Debug("Snapshot processed")
 }
 
 func startupOnExistingDatabase() {
 	// start bundle downloads that didn't finish
 	go func() {
-		deployments, err := getUnreadyDeployments()
+		deployments, err := dbMan.getUnreadyDeployments()
 
 		if err != nil && err != sql.ErrNoRows {
 			log.Panicf("unable to query database for unready deployments: %v", err)
diff --git a/pluginData.go b/pluginData.go
index ce1eace..8815183 100644
--- a/pluginData.go
+++ b/pluginData.go
@@ -1,3 +1,16 @@
+// Copyright 2017 Google Inc.
+//
+// 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.
 package apiGatewayConfDeploy
 
 import "github.com/30x/apid-core"