diff --git a/README.md b/README.md
index 9edbe7930601b16af937ca1ab5082916a4d28e09..1d69b99fd409c8675a6e15c11d518580722f7d7e 100644
--- a/README.md
+++ b/README.md
@@ -55,6 +55,10 @@ inspected by pre-defined aggregations (*queries*), that are shipped
 with the server configuration and can be queried via the RPC
 interface, which can take advantage of the SQLITE JSON extensions.
 
+The *application-specific key* is a separate and independent key space
+hooked off the primary (shard / type / resource_id) key, which allows
+one to store multiple entries for the same type and resource.
+
 Q: Isn't this just a way to achieve SQL sharding?
 
 A: In a sense, yes, but with RPC APIs tuned to a very specific use
diff --git a/server_test.go b/server_test.go
index ce7ae4abf11c7ae53a3b8b2fc4fcaeeef9cd8ba5..98329a8530bdaa94226e31f72c1a91d15e8be0fc 100644
--- a/server_test.go
+++ b/server_test.go
@@ -26,11 +26,11 @@ var (
 		Results: []QueryParam{
 			{
 				Name: "resource_id",
-				Type: "string",
+				Type: TypeString,
 			},
 			{
 				Name: "usage",
-				Type: "int",
+				Type: TypeInt,
 			},
 		},
 	}
@@ -39,11 +39,11 @@ var (
 		Results: []QueryParam{
 			{
 				Name: "timestamp",
-				Type: "timestamp",
+				Type: TypeTimestamp,
 			},
 			{
 				Name: "usage",
-				Type: "int",
+				Type: TypeInt,
 			},
 		},
 	}
diff --git a/server_webappdb_test.go b/server_webappdb_test.go
index 24400f6e03066ae097d74ab494c71ded45af1cf1..eb2c5690b899ef9bcb003f66a4d5cb004aa022da 100644
--- a/server_webappdb_test.go
+++ b/server_webappdb_test.go
@@ -13,25 +13,25 @@ var (
 SELECT
   resource_id,
   app_key,
-  json_extract(value_json, '$.name') as name,
+  json_extract(value_json, '$.appname') as appname,
   json_extract(value_json, '$.version') as version,
-  json_extract(value_json, '$.safe_version') as version,
+  json_extract(value_json, '$.safeversion') as safeversion,
   json_extract(value_json, '$.state') as state,
   json_extract(value_json, '$.vulninfo') as vulninfo
 FROM
   latest
 WHERE
   type = 'webapp' AND
-  name = :app
+  appname = :app
 `,
 		Results: []QueryParam{
-			{Name: "resource_id", Type: "string"},
-			{Name: "app_key", Type: "string"},
-			{Name: "name", Type: "string"},
-			{Name: "version", Type: "string"},
-			{Name: "safe_version", Type: "string"},
-			{Name: "state", Type: "string"},
-			{Name: "vulninfo", Type: "string"},
+			{Name: "resource_id", Type: TypeString},
+			{Name: "app_key", Type: TypeString},
+			{Name: "appname", Type: TypeString},
+			{Name: "version", Type: TypeString},
+			{Name: "safeversion", Type: TypeString},
+			{Name: "state", Type: TypeString},
+			{Name: "vulninfo", Type: TypeString},
 		},
 	}
 
@@ -39,18 +39,18 @@ WHERE
 		SQL: `
 SELECT
   COUNT(*) AS c,
-  json_extract(value_json, '$.name') as name,
+  json_extract(value_json, '$.appname') as appname,
   json_extract(value_json, '$.version') as version
   FROM latest
 WHERE
   type = 'webapp'
-  AND name = :app
+  AND appname = :app
 ORDER BY c DESC
 `,
 		Results: []QueryParam{
-			{Name: "count", Type: "int"},
-			{Name: "name", Type: "string"},
-			{Name: "version", Type: "string"},
+			{Name: "count", Type: TypeInt},
+			{Name: "appname", Type: TypeString},
+			{Name: "version", Type: TypeString},
 		},
 	}
 )
@@ -63,24 +63,23 @@ func (c *testCtx) loadWebappTestData(t testing.TB) {
 		Entries: []auxpb.LoadEntry{
 			{
 				ResourceID: "website1",
-				AppKey:     "path/1",
+				AppKey:     "/path/1",
 				ValueJSON: `
-{"name": "Wordpress", "version": "4.5.1", "safe_version": "5.6",
- "state": "vulnerable", "vulninfo": "FOO BAR PHP SHELL"}`,
+{"appname": "Wordpress", "version": "4.5.1", "safeversion": "5.6",
+ "state": "vulnerable", "vulninfo": "CVE-2019-17672"}`,
 			},
 			{
 				ResourceID: "website1",
-				AppKey:     "path/2",
+				AppKey:     "/path/2",
 				ValueJSON: `
-{"name": "Wordpress-plugin", "version": "0.1", "safe_version": "0.2",
- "state": "vulnerable", "vulninfo": "FOO BAR PHP SHELL"}`,
+{"appname": "Wordpress-plugin", "version": "0.1", "state": "ok"}`,
 			},
 			{
 				ResourceID: "website2",
-				AppKey:     "path/3",
+				AppKey:     "/path/3",
 				ValueJSON: `
-{"name": "Wordpress", "version": "4.5.1", "safe_version": "5.6",
- "state": "vulnerable", "vulninfo": "FOO BAR PHP SHELL"}`,
+{"appname": "Wordpress", "version": "4.5.1", "safeversion": "5.6",
+ "state": "vulnerable", "vulninfo": "CVE-2019-17672"}`,
 			},
 		},
 	}, nil)
@@ -113,6 +112,11 @@ func TestWebapp_Get(t *testing.T) {
 	if len(resp.Results) != 2 {
 		t.Fatalf("expected 2 results, got %d: %v", len(resp.Results), resp.Results)
 	}
+	for _, entry := range resp.Results {
+		if entry.Key.AppKey != "/path/1" && entry.Key.AppKey != "/path/2" {
+			t.Errorf("invalid app_key in result: %s", entry.Key.AppKey)
+		}
+	}
 }
 
 func TestWebapp_Query_Find(t *testing.T) {
@@ -137,6 +141,12 @@ func TestWebapp_Query_Find(t *testing.T) {
 	if resp.Results[0][3].(string) != "4.5.1" {
 		t.Fatalf("bad result: %v", resp.Results[0])
 	}
+	for _, r := range resp.Results {
+		appKey := r[1].(string)
+		if appKey != "/path/1" && appKey != "/path/3" {
+			t.Errorf("invalid app_key in result: %s", appKey)
+		}
+	}
 }
 
 func TestWebapp_Query_Count(t *testing.T) {