v23: syncbase: rename "table" to "collection"

Second half of part 1 of transition plan.

MultiPart: 1/3

Change-Id: If5a377c5ad1ae6bef4ac78aa0c549495470925fb
diff --git a/services/syncbase/.api b/services/syncbase/.api
index 8d740bb..4192fce 100644
--- a/services/syncbase/.api
+++ b/services/syncbase/.api
@@ -21,6 +21,8 @@
 pkg syncbase, func BlobFetchStateFromString(string) (BlobFetchState, error)
 pkg syncbase, func BlobManagerClient(string) BlobManagerClientStub
 pkg syncbase, func BlobManagerServer(BlobManagerServerMethods) BlobManagerServerStub
+pkg syncbase, func CollectionClient(string) CollectionClientStub
+pkg syncbase, func CollectionServer(CollectionServerMethods) CollectionServerStub
 pkg syncbase, func ConflictManagerClient(string) ConflictManagerClientStub
 pkg syncbase, func ConflictManagerServer(ConflictManagerServerMethods) ConflictManagerServerStub
 pkg syncbase, func DatabaseClient(string) DatabaseClientStub
@@ -47,8 +49,6 @@
 pkg syncbase, func ServiceServer(ServiceServerMethods) ServiceServerStub
 pkg syncbase, func SyncgroupManagerClient(string) SyncgroupManagerClientStub
 pkg syncbase, func SyncgroupManagerServer(SyncgroupManagerServerMethods) SyncgroupManagerServerStub
-pkg syncbase, func TableClient(string) TableClientStub
-pkg syncbase, func TableServer(TableServerMethods) TableServerStub
 pkg syncbase, func ValueSelectionFromString(string) (ValueSelection, error)
 pkg syncbase, func ValueStateFromString(string) (ValueState, error)
 pkg syncbase, method (*BatchInfo) FillVDLTarget(vdl.Target, *vdl.Type) error
@@ -86,6 +86,14 @@
 pkg syncbase, method (*BlobRef) FillVDLTarget(vdl.Target, *vdl.Type) error
 pkg syncbase, method (*BlobRef) MakeVDLTarget() vdl.Target
 pkg syncbase, method (*BlobRefTarget) FromString(string, *vdl.Type) error
+pkg syncbase, method (*CollectionRow) FillVDLTarget(vdl.Target, *vdl.Type) error
+pkg syncbase, method (*CollectionRow) MakeVDLTarget() vdl.Target
+pkg syncbase, method (*CollectionRowTarget) FinishField(vdl.Target, vdl.Target) error
+pkg syncbase, method (*CollectionRowTarget) FinishFields(vdl.FieldsTarget) error
+pkg syncbase, method (*CollectionRowTarget) StartField(string) (vdl.Target, vdl.Target, error)
+pkg syncbase, method (*CollectionRowTarget) StartFields(*vdl.Type) (vdl.FieldsTarget, error)
+pkg syncbase, method (*CollectionScanServerCallStub) Init(rpc.StreamServerCall)
+pkg syncbase, method (*CollectionScanServerCallStub) SendStream() interface {  Send(item KeyValue) error;}
 pkg syncbase, method (*ConflictDataTarget) FinishField(vdl.Target, vdl.Target) error
 pkg syncbase, method (*ConflictDataTarget) FinishFields(vdl.FieldsTarget) error
 pkg syncbase, method (*ConflictDataTarget) StartField(string) (vdl.Target, vdl.Target, error)
@@ -187,14 +195,6 @@
 pkg syncbase, method (*SyncgroupSpecTarget) FinishFields(vdl.FieldsTarget) error
 pkg syncbase, method (*SyncgroupSpecTarget) StartField(string) (vdl.Target, vdl.Target, error)
 pkg syncbase, method (*SyncgroupSpecTarget) StartFields(*vdl.Type) (vdl.FieldsTarget, error)
-pkg syncbase, method (*TableRow) FillVDLTarget(vdl.Target, *vdl.Type) error
-pkg syncbase, method (*TableRow) MakeVDLTarget() vdl.Target
-pkg syncbase, method (*TableRowTarget) FinishField(vdl.Target, vdl.Target) error
-pkg syncbase, method (*TableRowTarget) FinishFields(vdl.FieldsTarget) error
-pkg syncbase, method (*TableRowTarget) StartField(string) (vdl.Target, vdl.Target, error)
-pkg syncbase, method (*TableRowTarget) StartFields(*vdl.Type) (vdl.FieldsTarget, error)
-pkg syncbase, method (*TableScanServerCallStub) Init(rpc.StreamServerCall)
-pkg syncbase, method (*TableScanServerCallStub) SendStream() interface {  Send(item KeyValue) error;}
 pkg syncbase, method (*Value) FillVDLTarget(vdl.Target, *vdl.Type) error
 pkg syncbase, method (*Value) MakeVDLTarget() vdl.Target
 pkg syncbase, method (*ValueSelection) FillVDLTarget(vdl.Target, *vdl.Type) error
@@ -239,24 +239,18 @@
 pkg syncbase, method (ResolverType) String() string
 pkg syncbase, method (ValueSelection) String() string
 pkg syncbase, method (ValueState) String() string
-pkg syncbase, type AppClientMethods interface { Create, Destroy, Exists, GetPermissions, SetPermissions }
 pkg syncbase, type AppClientMethods interface, Create(*context.T, access.Permissions, ...rpc.CallOpt) error
 pkg syncbase, type AppClientMethods interface, Destroy(*context.T, ...rpc.CallOpt) error
 pkg syncbase, type AppClientMethods interface, Exists(*context.T, ...rpc.CallOpt) (bool, error)
-pkg syncbase, type AppClientMethods interface, GetPermissions(*context.T, ...rpc.CallOpt) (access.Permissions, string, error)
-pkg syncbase, type AppClientMethods interface, SetPermissions(*context.T, access.Permissions, string, ...rpc.CallOpt) error
-pkg syncbase, type AppClientStub interface { Create, Destroy, Exists, GetPermissions, SetPermissions }
+pkg syncbase, type AppClientMethods interface, unexported methods
 pkg syncbase, type AppClientStub interface, Create(*context.T, access.Permissions, ...rpc.CallOpt) error
 pkg syncbase, type AppClientStub interface, Destroy(*context.T, ...rpc.CallOpt) error
 pkg syncbase, type AppClientStub interface, Exists(*context.T, ...rpc.CallOpt) (bool, error)
-pkg syncbase, type AppClientStub interface, GetPermissions(*context.T, ...rpc.CallOpt) (access.Permissions, string, error)
-pkg syncbase, type AppClientStub interface, SetPermissions(*context.T, access.Permissions, string, ...rpc.CallOpt) error
-pkg syncbase, type AppServerMethods interface { Create, Destroy, Exists, GetPermissions, SetPermissions }
+pkg syncbase, type AppClientStub interface, unexported methods
 pkg syncbase, type AppServerMethods interface, Create(*context.T, rpc.ServerCall, access.Permissions) error
 pkg syncbase, type AppServerMethods interface, Destroy(*context.T, rpc.ServerCall) error
 pkg syncbase, type AppServerMethods interface, Exists(*context.T, rpc.ServerCall) (bool, error)
-pkg syncbase, type AppServerMethods interface, GetPermissions(*context.T, rpc.ServerCall) (access.Permissions, string, error)
-pkg syncbase, type AppServerMethods interface, SetPermissions(*context.T, rpc.ServerCall, access.Permissions, string) error
+pkg syncbase, type AppServerMethods interface, unexported methods
 pkg syncbase, type AppServerStub interface, Describe__() []rpc.InterfaceDesc
 pkg syncbase, type AppServerStub interface, unexported methods
 pkg syncbase, type AppServerStubMethods AppServerMethods
@@ -302,7 +296,6 @@
 pkg syncbase, type BlobManagerClientMethods interface, PinBlob(*context.T, BlobRef, ...rpc.CallOpt) error
 pkg syncbase, type BlobManagerClientMethods interface, PutBlob(*context.T, BlobRef, ...rpc.CallOpt) (BlobManagerPutBlobClientCall, error)
 pkg syncbase, type BlobManagerClientMethods interface, UnpinBlob(*context.T, BlobRef, ...rpc.CallOpt) error
-pkg syncbase, type BlobManagerClientStub interface { CommitBlob, CreateBlob, DeleteBlob, FetchBlob, GetBlob, GetBlobSize, KeepBlob, PinBlob, PutBlob, UnpinBlob }
 pkg syncbase, type BlobManagerClientStub interface, CommitBlob(*context.T, BlobRef, ...rpc.CallOpt) error
 pkg syncbase, type BlobManagerClientStub interface, CreateBlob(*context.T, ...rpc.CallOpt) (BlobRef, error)
 pkg syncbase, type BlobManagerClientStub interface, DeleteBlob(*context.T, BlobRef, ...rpc.CallOpt) error
@@ -313,19 +306,14 @@
 pkg syncbase, type BlobManagerClientStub interface, PinBlob(*context.T, BlobRef, ...rpc.CallOpt) error
 pkg syncbase, type BlobManagerClientStub interface, PutBlob(*context.T, BlobRef, ...rpc.CallOpt) (BlobManagerPutBlobClientCall, error)
 pkg syncbase, type BlobManagerClientStub interface, UnpinBlob(*context.T, BlobRef, ...rpc.CallOpt) error
+pkg syncbase, type BlobManagerClientStub interface, unexported methods
 pkg syncbase, type BlobManagerFetchBlobClientCall interface { Finish, RecvStream }
 pkg syncbase, type BlobManagerFetchBlobClientCall interface, Finish() error
 pkg syncbase, type BlobManagerFetchBlobClientCall interface, RecvStream() interface {  Advance() bool;; Value() BlobFetchStatus;; Err() error;}
 pkg syncbase, type BlobManagerFetchBlobClientStream interface { RecvStream }
 pkg syncbase, type BlobManagerFetchBlobClientStream interface, RecvStream() interface {  Advance() bool;; Value() BlobFetchStatus;; Err() error;}
-pkg syncbase, type BlobManagerFetchBlobServerCall interface { GrantedBlessings, LocalEndpoint, RemoteEndpoint, Security, SendStream, Server, Suffix }
-pkg syncbase, type BlobManagerFetchBlobServerCall interface, GrantedBlessings() security.Blessings
-pkg syncbase, type BlobManagerFetchBlobServerCall interface, LocalEndpoint() naming.Endpoint
-pkg syncbase, type BlobManagerFetchBlobServerCall interface, RemoteEndpoint() naming.Endpoint
-pkg syncbase, type BlobManagerFetchBlobServerCall interface, Security() security.Call
 pkg syncbase, type BlobManagerFetchBlobServerCall interface, SendStream() interface {  Send(item BlobFetchStatus) error;}
-pkg syncbase, type BlobManagerFetchBlobServerCall interface, Server() Server
-pkg syncbase, type BlobManagerFetchBlobServerCall interface, Suffix() string
+pkg syncbase, type BlobManagerFetchBlobServerCall interface, unexported methods
 pkg syncbase, type BlobManagerFetchBlobServerCallStub struct
 pkg syncbase, type BlobManagerFetchBlobServerCallStub struct, embedded rpc.StreamServerCall
 pkg syncbase, type BlobManagerFetchBlobServerStream interface { SendStream }
@@ -335,14 +323,8 @@
 pkg syncbase, type BlobManagerGetBlobClientCall interface, RecvStream() interface {  Advance() bool;; Value() []byte;; Err() error;}
 pkg syncbase, type BlobManagerGetBlobClientStream interface { RecvStream }
 pkg syncbase, type BlobManagerGetBlobClientStream interface, RecvStream() interface {  Advance() bool;; Value() []byte;; Err() error;}
-pkg syncbase, type BlobManagerGetBlobServerCall interface { GrantedBlessings, LocalEndpoint, RemoteEndpoint, Security, SendStream, Server, Suffix }
-pkg syncbase, type BlobManagerGetBlobServerCall interface, GrantedBlessings() security.Blessings
-pkg syncbase, type BlobManagerGetBlobServerCall interface, LocalEndpoint() naming.Endpoint
-pkg syncbase, type BlobManagerGetBlobServerCall interface, RemoteEndpoint() naming.Endpoint
-pkg syncbase, type BlobManagerGetBlobServerCall interface, Security() security.Call
 pkg syncbase, type BlobManagerGetBlobServerCall interface, SendStream() interface {  Send(item []byte) error;}
-pkg syncbase, type BlobManagerGetBlobServerCall interface, Server() Server
-pkg syncbase, type BlobManagerGetBlobServerCall interface, Suffix() string
+pkg syncbase, type BlobManagerGetBlobServerCall interface, unexported methods
 pkg syncbase, type BlobManagerGetBlobServerCallStub struct
 pkg syncbase, type BlobManagerGetBlobServerCallStub struct, embedded rpc.StreamServerCall
 pkg syncbase, type BlobManagerGetBlobServerStream interface { SendStream }
@@ -352,14 +334,8 @@
 pkg syncbase, type BlobManagerPutBlobClientCall interface, SendStream() interface {  Send(item []byte) error;; Close() error;}
 pkg syncbase, type BlobManagerPutBlobClientStream interface { SendStream }
 pkg syncbase, type BlobManagerPutBlobClientStream interface, SendStream() interface {  Send(item []byte) error;; Close() error;}
-pkg syncbase, type BlobManagerPutBlobServerCall interface { GrantedBlessings, LocalEndpoint, RecvStream, RemoteEndpoint, Security, Server, Suffix }
-pkg syncbase, type BlobManagerPutBlobServerCall interface, GrantedBlessings() security.Blessings
-pkg syncbase, type BlobManagerPutBlobServerCall interface, LocalEndpoint() naming.Endpoint
 pkg syncbase, type BlobManagerPutBlobServerCall interface, RecvStream() interface {  Advance() bool;; Value() []byte;; Err() error;}
-pkg syncbase, type BlobManagerPutBlobServerCall interface, RemoteEndpoint() naming.Endpoint
-pkg syncbase, type BlobManagerPutBlobServerCall interface, Security() security.Call
-pkg syncbase, type BlobManagerPutBlobServerCall interface, Server() Server
-pkg syncbase, type BlobManagerPutBlobServerCall interface, Suffix() string
+pkg syncbase, type BlobManagerPutBlobServerCall interface, unexported methods
 pkg syncbase, type BlobManagerPutBlobServerCallStub struct
 pkg syncbase, type BlobManagerPutBlobServerCallStub struct, embedded rpc.StreamServerCall
 pkg syncbase, type BlobManagerPutBlobServerStream interface { RecvStream }
@@ -402,6 +378,80 @@
 pkg syncbase, type BlobRefTarget struct
 pkg syncbase, type BlobRefTarget struct, Value *BlobRef
 pkg syncbase, type BlobRefTarget struct, embedded vdl.TargetBase
+pkg syncbase, type CollectionClientMethods interface { Create, DeletePrefixPermissions, DeleteRange, Destroy, Exists, GetPermissions, GetPrefixPermissions, Scan, SetPermissions, SetPrefixPermissions }
+pkg syncbase, type CollectionClientMethods interface, Create(*context.T, int32, access.Permissions, ...rpc.CallOpt) error
+pkg syncbase, type CollectionClientMethods interface, DeletePrefixPermissions(*context.T, int32, string, ...rpc.CallOpt) error
+pkg syncbase, type CollectionClientMethods interface, DeleteRange(*context.T, int32, []byte, []byte, ...rpc.CallOpt) error
+pkg syncbase, type CollectionClientMethods interface, Destroy(*context.T, int32, ...rpc.CallOpt) error
+pkg syncbase, type CollectionClientMethods interface, Exists(*context.T, int32, ...rpc.CallOpt) (bool, error)
+pkg syncbase, type CollectionClientMethods interface, GetPermissions(*context.T, int32, ...rpc.CallOpt) (access.Permissions, error)
+pkg syncbase, type CollectionClientMethods interface, GetPrefixPermissions(*context.T, int32, string, ...rpc.CallOpt) ([]PrefixPermissions, error)
+pkg syncbase, type CollectionClientMethods interface, Scan(*context.T, int32, []byte, []byte, ...rpc.CallOpt) (CollectionScanClientCall, error)
+pkg syncbase, type CollectionClientMethods interface, SetPermissions(*context.T, int32, access.Permissions, ...rpc.CallOpt) error
+pkg syncbase, type CollectionClientMethods interface, SetPrefixPermissions(*context.T, int32, string, access.Permissions, ...rpc.CallOpt) error
+pkg syncbase, type CollectionClientStub interface, Create(*context.T, int32, access.Permissions, ...rpc.CallOpt) error
+pkg syncbase, type CollectionClientStub interface, DeletePrefixPermissions(*context.T, int32, string, ...rpc.CallOpt) error
+pkg syncbase, type CollectionClientStub interface, DeleteRange(*context.T, int32, []byte, []byte, ...rpc.CallOpt) error
+pkg syncbase, type CollectionClientStub interface, Destroy(*context.T, int32, ...rpc.CallOpt) error
+pkg syncbase, type CollectionClientStub interface, Exists(*context.T, int32, ...rpc.CallOpt) (bool, error)
+pkg syncbase, type CollectionClientStub interface, GetPermissions(*context.T, int32, ...rpc.CallOpt) (access.Permissions, error)
+pkg syncbase, type CollectionClientStub interface, GetPrefixPermissions(*context.T, int32, string, ...rpc.CallOpt) ([]PrefixPermissions, error)
+pkg syncbase, type CollectionClientStub interface, Scan(*context.T, int32, []byte, []byte, ...rpc.CallOpt) (CollectionScanClientCall, error)
+pkg syncbase, type CollectionClientStub interface, SetPermissions(*context.T, int32, access.Permissions, ...rpc.CallOpt) error
+pkg syncbase, type CollectionClientStub interface, SetPrefixPermissions(*context.T, int32, string, access.Permissions, ...rpc.CallOpt) error
+pkg syncbase, type CollectionClientStub interface, unexported methods
+pkg syncbase, type CollectionRow struct
+pkg syncbase, type CollectionRow struct, CollectionName string
+pkg syncbase, type CollectionRow struct, Row string
+pkg syncbase, type CollectionRowTarget struct
+pkg syncbase, type CollectionRowTarget struct, Value *CollectionRow
+pkg syncbase, type CollectionRowTarget struct, embedded vdl.FieldsTargetBase
+pkg syncbase, type CollectionRowTarget struct, embedded vdl.TargetBase
+pkg syncbase, type CollectionScanClientCall interface { Finish, RecvStream }
+pkg syncbase, type CollectionScanClientCall interface, Finish() error
+pkg syncbase, type CollectionScanClientCall interface, RecvStream() interface {  Advance() bool;; Value() KeyValue;; Err() error;}
+pkg syncbase, type CollectionScanClientStream interface { RecvStream }
+pkg syncbase, type CollectionScanClientStream interface, RecvStream() interface {  Advance() bool;; Value() KeyValue;; Err() error;}
+pkg syncbase, type CollectionScanServerCall interface, SendStream() interface {  Send(item KeyValue) error;}
+pkg syncbase, type CollectionScanServerCall interface, unexported methods
+pkg syncbase, type CollectionScanServerCallStub struct
+pkg syncbase, type CollectionScanServerCallStub struct, embedded rpc.StreamServerCall
+pkg syncbase, type CollectionScanServerStream interface { SendStream }
+pkg syncbase, type CollectionScanServerStream interface, SendStream() interface {  Send(item KeyValue) error;}
+pkg syncbase, type CollectionServerMethods interface { Create, DeletePrefixPermissions, DeleteRange, Destroy, Exists, GetPermissions, GetPrefixPermissions, Scan, SetPermissions, SetPrefixPermissions }
+pkg syncbase, type CollectionServerMethods interface, Create(*context.T, rpc.ServerCall, int32, access.Permissions) error
+pkg syncbase, type CollectionServerMethods interface, DeletePrefixPermissions(*context.T, rpc.ServerCall, int32, string) error
+pkg syncbase, type CollectionServerMethods interface, DeleteRange(*context.T, rpc.ServerCall, int32, []byte, []byte) error
+pkg syncbase, type CollectionServerMethods interface, Destroy(*context.T, rpc.ServerCall, int32) error
+pkg syncbase, type CollectionServerMethods interface, Exists(*context.T, rpc.ServerCall, int32) (bool, error)
+pkg syncbase, type CollectionServerMethods interface, GetPermissions(*context.T, rpc.ServerCall, int32) (access.Permissions, error)
+pkg syncbase, type CollectionServerMethods interface, GetPrefixPermissions(*context.T, rpc.ServerCall, int32, string) ([]PrefixPermissions, error)
+pkg syncbase, type CollectionServerMethods interface, Scan(*context.T, CollectionScanServerCall, int32, []byte, []byte) error
+pkg syncbase, type CollectionServerMethods interface, SetPermissions(*context.T, rpc.ServerCall, int32, access.Permissions) error
+pkg syncbase, type CollectionServerMethods interface, SetPrefixPermissions(*context.T, rpc.ServerCall, int32, string, access.Permissions) error
+pkg syncbase, type CollectionServerStub interface { Create, DeletePrefixPermissions, DeleteRange, Describe__, Destroy, Exists, GetPermissions, GetPrefixPermissions, Scan, SetPermissions, SetPrefixPermissions }
+pkg syncbase, type CollectionServerStub interface, Create(*context.T, rpc.ServerCall, int32, access.Permissions) error
+pkg syncbase, type CollectionServerStub interface, DeletePrefixPermissions(*context.T, rpc.ServerCall, int32, string) error
+pkg syncbase, type CollectionServerStub interface, DeleteRange(*context.T, rpc.ServerCall, int32, []byte, []byte) error
+pkg syncbase, type CollectionServerStub interface, Describe__() []rpc.InterfaceDesc
+pkg syncbase, type CollectionServerStub interface, Destroy(*context.T, rpc.ServerCall, int32) error
+pkg syncbase, type CollectionServerStub interface, Exists(*context.T, rpc.ServerCall, int32) (bool, error)
+pkg syncbase, type CollectionServerStub interface, GetPermissions(*context.T, rpc.ServerCall, int32) (access.Permissions, error)
+pkg syncbase, type CollectionServerStub interface, GetPrefixPermissions(*context.T, rpc.ServerCall, int32, string) ([]PrefixPermissions, error)
+pkg syncbase, type CollectionServerStub interface, Scan(*context.T, *CollectionScanServerCallStub, int32, []byte, []byte) error
+pkg syncbase, type CollectionServerStub interface, SetPermissions(*context.T, rpc.ServerCall, int32, access.Permissions) error
+pkg syncbase, type CollectionServerStub interface, SetPrefixPermissions(*context.T, rpc.ServerCall, int32, string, access.Permissions) error
+pkg syncbase, type CollectionServerStubMethods interface { Create, DeletePrefixPermissions, DeleteRange, Destroy, Exists, GetPermissions, GetPrefixPermissions, Scan, SetPermissions, SetPrefixPermissions }
+pkg syncbase, type CollectionServerStubMethods interface, Create(*context.T, rpc.ServerCall, int32, access.Permissions) error
+pkg syncbase, type CollectionServerStubMethods interface, DeletePrefixPermissions(*context.T, rpc.ServerCall, int32, string) error
+pkg syncbase, type CollectionServerStubMethods interface, DeleteRange(*context.T, rpc.ServerCall, int32, []byte, []byte) error
+pkg syncbase, type CollectionServerStubMethods interface, Destroy(*context.T, rpc.ServerCall, int32) error
+pkg syncbase, type CollectionServerStubMethods interface, Exists(*context.T, rpc.ServerCall, int32) (bool, error)
+pkg syncbase, type CollectionServerStubMethods interface, GetPermissions(*context.T, rpc.ServerCall, int32) (access.Permissions, error)
+pkg syncbase, type CollectionServerStubMethods interface, GetPrefixPermissions(*context.T, rpc.ServerCall, int32, string) ([]PrefixPermissions, error)
+pkg syncbase, type CollectionServerStubMethods interface, Scan(*context.T, *CollectionScanServerCallStub, int32, []byte, []byte) error
+pkg syncbase, type CollectionServerStubMethods interface, SetPermissions(*context.T, rpc.ServerCall, int32, access.Permissions) error
+pkg syncbase, type CollectionServerStubMethods interface, SetPrefixPermissions(*context.T, rpc.ServerCall, int32, string, access.Permissions) error
 pkg syncbase, type ConflictData interface, FillVDLTarget(vdl.Target, *vdl.Type) error
 pkg syncbase, type ConflictData interface, Index() int
 pkg syncbase, type ConflictData interface, Interface() interface{}
@@ -424,8 +474,8 @@
 pkg syncbase, type ConflictInfoTarget struct, embedded vdl.TargetBase
 pkg syncbase, type ConflictManagerClientMethods interface { StartConflictResolver }
 pkg syncbase, type ConflictManagerClientMethods interface, StartConflictResolver(*context.T, ...rpc.CallOpt) (ConflictManagerStartConflictResolverClientCall, error)
-pkg syncbase, type ConflictManagerClientStub interface { StartConflictResolver }
 pkg syncbase, type ConflictManagerClientStub interface, StartConflictResolver(*context.T, ...rpc.CallOpt) (ConflictManagerStartConflictResolverClientCall, error)
+pkg syncbase, type ConflictManagerClientStub interface, unexported methods
 pkg syncbase, type ConflictManagerServerMethods interface { StartConflictResolver }
 pkg syncbase, type ConflictManagerServerMethods interface, StartConflictResolver(*context.T, ConflictManagerStartConflictResolverServerCall) error
 pkg syncbase, type ConflictManagerServerStub interface { Describe__, StartConflictResolver }
@@ -440,15 +490,9 @@
 pkg syncbase, type ConflictManagerStartConflictResolverClientStream interface { RecvStream, SendStream }
 pkg syncbase, type ConflictManagerStartConflictResolverClientStream interface, RecvStream() interface {  Advance() bool;; Value() ConflictInfo;; Err() error;}
 pkg syncbase, type ConflictManagerStartConflictResolverClientStream interface, SendStream() interface {  Send(item ResolutionInfo) error;; Close() error;}
-pkg syncbase, type ConflictManagerStartConflictResolverServerCall interface { GrantedBlessings, LocalEndpoint, RecvStream, RemoteEndpoint, Security, SendStream, Server, Suffix }
-pkg syncbase, type ConflictManagerStartConflictResolverServerCall interface, GrantedBlessings() security.Blessings
-pkg syncbase, type ConflictManagerStartConflictResolverServerCall interface, LocalEndpoint() naming.Endpoint
 pkg syncbase, type ConflictManagerStartConflictResolverServerCall interface, RecvStream() interface {  Advance() bool;; Value() ResolutionInfo;; Err() error;}
-pkg syncbase, type ConflictManagerStartConflictResolverServerCall interface, RemoteEndpoint() naming.Endpoint
-pkg syncbase, type ConflictManagerStartConflictResolverServerCall interface, Security() security.Call
 pkg syncbase, type ConflictManagerStartConflictResolverServerCall interface, SendStream() interface {  Send(item ConflictInfo) error;}
-pkg syncbase, type ConflictManagerStartConflictResolverServerCall interface, Server() Server
-pkg syncbase, type ConflictManagerStartConflictResolverServerCall interface, Suffix() string
+pkg syncbase, type ConflictManagerStartConflictResolverServerCall interface, unexported methods
 pkg syncbase, type ConflictManagerStartConflictResolverServerCallStub struct
 pkg syncbase, type ConflictManagerStartConflictResolverServerCallStub struct, embedded rpc.StreamServerCall
 pkg syncbase, type ConflictManagerStartConflictResolverServerStream interface { RecvStream, SendStream }
@@ -461,15 +505,14 @@
 pkg syncbase, type CrPolicyTarget struct, embedded vdl.FieldsTargetBase
 pkg syncbase, type CrPolicyTarget struct, embedded vdl.TargetBase
 pkg syncbase, type CrRule struct
+pkg syncbase, type CrRule struct, CollectionName string
 pkg syncbase, type CrRule struct, KeyPrefix string
 pkg syncbase, type CrRule struct, Resolver ResolverType
-pkg syncbase, type CrRule struct, TableName string
 pkg syncbase, type CrRule struct, Type string
 pkg syncbase, type CrRuleTarget struct
 pkg syncbase, type CrRuleTarget struct, Value *CrRule
 pkg syncbase, type CrRuleTarget struct, embedded vdl.FieldsTargetBase
 pkg syncbase, type CrRuleTarget struct, embedded vdl.TargetBase
-pkg syncbase, type DatabaseClientMethods interface { Abort, BeginBatch, Commit, CommitBlob, Create, CreateBlob, CreateSyncgroup, DeleteBlob, Destroy, DestroySyncgroup, EjectFromSyncgroup, Exec, Exists, FetchBlob, GetBlob, GetBlobSize, GetPermissions, GetResumeMarker, GetSchemaMetadata, GetSyncgroupMembers, GetSyncgroupNames, GetSyncgroupSpec, JoinSyncgroup, KeepBlob, LeaveSyncgroup, ListTables, PauseSync, PinBlob, PutBlob, ResumeSync, SetPermissions, SetSchemaMetadata, SetSyncgroupSpec, StartConflictResolver, UnpinBlob, WatchGlob }
 pkg syncbase, type DatabaseClientMethods interface, Abort(*context.T, int32, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientMethods interface, BeginBatch(*context.T, int32, BatchOptions, ...rpc.CallOpt) (string, error)
 pkg syncbase, type DatabaseClientMethods interface, Commit(*context.T, int32, ...rpc.CallOpt) error
@@ -486,7 +529,6 @@
 pkg syncbase, type DatabaseClientMethods interface, FetchBlob(*context.T, BlobRef, uint64, ...rpc.CallOpt) (BlobManagerFetchBlobClientCall, error)
 pkg syncbase, type DatabaseClientMethods interface, GetBlob(*context.T, BlobRef, int64, ...rpc.CallOpt) (BlobManagerGetBlobClientCall, error)
 pkg syncbase, type DatabaseClientMethods interface, GetBlobSize(*context.T, BlobRef, ...rpc.CallOpt) (int64, error)
-pkg syncbase, type DatabaseClientMethods interface, GetPermissions(*context.T, ...rpc.CallOpt) (access.Permissions, string, error)
 pkg syncbase, type DatabaseClientMethods interface, GetResumeMarker(*context.T, ...rpc.CallOpt) (watch.ResumeMarker, error)
 pkg syncbase, type DatabaseClientMethods interface, GetSchemaMetadata(*context.T, ...rpc.CallOpt) (SchemaMetadata, error)
 pkg syncbase, type DatabaseClientMethods interface, GetSyncgroupMembers(*context.T, string, ...rpc.CallOpt) (map[string]SyncgroupMemberInfo, error)
@@ -495,18 +537,16 @@
 pkg syncbase, type DatabaseClientMethods interface, JoinSyncgroup(*context.T, string, SyncgroupMemberInfo, ...rpc.CallOpt) (SyncgroupSpec, error)
 pkg syncbase, type DatabaseClientMethods interface, KeepBlob(*context.T, BlobRef, uint64, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientMethods interface, LeaveSyncgroup(*context.T, string, ...rpc.CallOpt) error
-pkg syncbase, type DatabaseClientMethods interface, ListTables(*context.T, ...rpc.CallOpt) ([]string, error)
+pkg syncbase, type DatabaseClientMethods interface, ListCollections(*context.T, ...rpc.CallOpt) ([]string, error)
 pkg syncbase, type DatabaseClientMethods interface, PauseSync(*context.T, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientMethods interface, PinBlob(*context.T, BlobRef, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientMethods interface, PutBlob(*context.T, BlobRef, ...rpc.CallOpt) (BlobManagerPutBlobClientCall, error)
 pkg syncbase, type DatabaseClientMethods interface, ResumeSync(*context.T, ...rpc.CallOpt) error
-pkg syncbase, type DatabaseClientMethods interface, SetPermissions(*context.T, access.Permissions, string, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientMethods interface, SetSchemaMetadata(*context.T, SchemaMetadata, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientMethods interface, SetSyncgroupSpec(*context.T, string, SyncgroupSpec, string, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientMethods interface, StartConflictResolver(*context.T, ...rpc.CallOpt) (ConflictManagerStartConflictResolverClientCall, error)
 pkg syncbase, type DatabaseClientMethods interface, UnpinBlob(*context.T, BlobRef, ...rpc.CallOpt) error
-pkg syncbase, type DatabaseClientMethods interface, WatchGlob(*context.T, GlobRequest, ...rpc.CallOpt) (GlobWatcherWatchGlobClientCall, error)
-pkg syncbase, type DatabaseClientStub interface { Abort, BeginBatch, Commit, CommitBlob, Create, CreateBlob, CreateSyncgroup, DeleteBlob, Destroy, DestroySyncgroup, EjectFromSyncgroup, Exec, Exists, FetchBlob, GetBlob, GetBlobSize, GetPermissions, GetResumeMarker, GetSchemaMetadata, GetSyncgroupMembers, GetSyncgroupNames, GetSyncgroupSpec, JoinSyncgroup, KeepBlob, LeaveSyncgroup, ListTables, PauseSync, PinBlob, PutBlob, ResumeSync, SetPermissions, SetSchemaMetadata, SetSyncgroupSpec, StartConflictResolver, UnpinBlob, WatchGlob }
+pkg syncbase, type DatabaseClientMethods interface, unexported methods
 pkg syncbase, type DatabaseClientStub interface, Abort(*context.T, int32, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientStub interface, BeginBatch(*context.T, int32, BatchOptions, ...rpc.CallOpt) (string, error)
 pkg syncbase, type DatabaseClientStub interface, Commit(*context.T, int32, ...rpc.CallOpt) error
@@ -523,7 +563,6 @@
 pkg syncbase, type DatabaseClientStub interface, FetchBlob(*context.T, BlobRef, uint64, ...rpc.CallOpt) (BlobManagerFetchBlobClientCall, error)
 pkg syncbase, type DatabaseClientStub interface, GetBlob(*context.T, BlobRef, int64, ...rpc.CallOpt) (BlobManagerGetBlobClientCall, error)
 pkg syncbase, type DatabaseClientStub interface, GetBlobSize(*context.T, BlobRef, ...rpc.CallOpt) (int64, error)
-pkg syncbase, type DatabaseClientStub interface, GetPermissions(*context.T, ...rpc.CallOpt) (access.Permissions, string, error)
 pkg syncbase, type DatabaseClientStub interface, GetResumeMarker(*context.T, ...rpc.CallOpt) (watch.ResumeMarker, error)
 pkg syncbase, type DatabaseClientStub interface, GetSchemaMetadata(*context.T, ...rpc.CallOpt) (SchemaMetadata, error)
 pkg syncbase, type DatabaseClientStub interface, GetSyncgroupMembers(*context.T, string, ...rpc.CallOpt) (map[string]SyncgroupMemberInfo, error)
@@ -532,35 +571,27 @@
 pkg syncbase, type DatabaseClientStub interface, JoinSyncgroup(*context.T, string, SyncgroupMemberInfo, ...rpc.CallOpt) (SyncgroupSpec, error)
 pkg syncbase, type DatabaseClientStub interface, KeepBlob(*context.T, BlobRef, uint64, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientStub interface, LeaveSyncgroup(*context.T, string, ...rpc.CallOpt) error
-pkg syncbase, type DatabaseClientStub interface, ListTables(*context.T, ...rpc.CallOpt) ([]string, error)
+pkg syncbase, type DatabaseClientStub interface, ListCollections(*context.T, ...rpc.CallOpt) ([]string, error)
 pkg syncbase, type DatabaseClientStub interface, PauseSync(*context.T, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientStub interface, PinBlob(*context.T, BlobRef, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientStub interface, PutBlob(*context.T, BlobRef, ...rpc.CallOpt) (BlobManagerPutBlobClientCall, error)
 pkg syncbase, type DatabaseClientStub interface, ResumeSync(*context.T, ...rpc.CallOpt) error
-pkg syncbase, type DatabaseClientStub interface, SetPermissions(*context.T, access.Permissions, string, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientStub interface, SetSchemaMetadata(*context.T, SchemaMetadata, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientStub interface, SetSyncgroupSpec(*context.T, string, SyncgroupSpec, string, ...rpc.CallOpt) error
 pkg syncbase, type DatabaseClientStub interface, StartConflictResolver(*context.T, ...rpc.CallOpt) (ConflictManagerStartConflictResolverClientCall, error)
 pkg syncbase, type DatabaseClientStub interface, UnpinBlob(*context.T, BlobRef, ...rpc.CallOpt) error
-pkg syncbase, type DatabaseClientStub interface, WatchGlob(*context.T, GlobRequest, ...rpc.CallOpt) (GlobWatcherWatchGlobClientCall, error)
+pkg syncbase, type DatabaseClientStub interface, unexported methods
 pkg syncbase, type DatabaseExecClientCall interface { Finish, RecvStream }
 pkg syncbase, type DatabaseExecClientCall interface, Finish() error
 pkg syncbase, type DatabaseExecClientCall interface, RecvStream() interface {  Advance() bool;; Value() []*vom.RawBytes;; Err() error;}
 pkg syncbase, type DatabaseExecClientStream interface { RecvStream }
 pkg syncbase, type DatabaseExecClientStream interface, RecvStream() interface {  Advance() bool;; Value() []*vom.RawBytes;; Err() error;}
-pkg syncbase, type DatabaseExecServerCall interface { GrantedBlessings, LocalEndpoint, RemoteEndpoint, Security, SendStream, Server, Suffix }
-pkg syncbase, type DatabaseExecServerCall interface, GrantedBlessings() security.Blessings
-pkg syncbase, type DatabaseExecServerCall interface, LocalEndpoint() naming.Endpoint
-pkg syncbase, type DatabaseExecServerCall interface, RemoteEndpoint() naming.Endpoint
-pkg syncbase, type DatabaseExecServerCall interface, Security() security.Call
 pkg syncbase, type DatabaseExecServerCall interface, SendStream() interface {  Send(item []*vom.RawBytes) error;}
-pkg syncbase, type DatabaseExecServerCall interface, Server() Server
-pkg syncbase, type DatabaseExecServerCall interface, Suffix() string
+pkg syncbase, type DatabaseExecServerCall interface, unexported methods
 pkg syncbase, type DatabaseExecServerCallStub struct
 pkg syncbase, type DatabaseExecServerCallStub struct, embedded rpc.StreamServerCall
 pkg syncbase, type DatabaseExecServerStream interface { SendStream }
 pkg syncbase, type DatabaseExecServerStream interface, SendStream() interface {  Send(item []*vom.RawBytes) error;}
-pkg syncbase, type DatabaseServerMethods interface { Abort, BeginBatch, Commit, CommitBlob, Create, CreateBlob, CreateSyncgroup, DeleteBlob, Destroy, DestroySyncgroup, EjectFromSyncgroup, Exec, Exists, FetchBlob, GetBlob, GetBlobSize, GetPermissions, GetResumeMarker, GetSchemaMetadata, GetSyncgroupMembers, GetSyncgroupNames, GetSyncgroupSpec, JoinSyncgroup, KeepBlob, LeaveSyncgroup, ListTables, PauseSync, PinBlob, PutBlob, ResumeSync, SetPermissions, SetSchemaMetadata, SetSyncgroupSpec, StartConflictResolver, UnpinBlob, WatchGlob }
 pkg syncbase, type DatabaseServerMethods interface, Abort(*context.T, rpc.ServerCall, int32) error
 pkg syncbase, type DatabaseServerMethods interface, BeginBatch(*context.T, rpc.ServerCall, int32, BatchOptions) (string, error)
 pkg syncbase, type DatabaseServerMethods interface, Commit(*context.T, rpc.ServerCall, int32) error
@@ -577,7 +608,6 @@
 pkg syncbase, type DatabaseServerMethods interface, FetchBlob(*context.T, BlobManagerFetchBlobServerCall, BlobRef, uint64) error
 pkg syncbase, type DatabaseServerMethods interface, GetBlob(*context.T, BlobManagerGetBlobServerCall, BlobRef, int64) error
 pkg syncbase, type DatabaseServerMethods interface, GetBlobSize(*context.T, rpc.ServerCall, BlobRef) (int64, error)
-pkg syncbase, type DatabaseServerMethods interface, GetPermissions(*context.T, rpc.ServerCall) (access.Permissions, string, error)
 pkg syncbase, type DatabaseServerMethods interface, GetResumeMarker(*context.T, rpc.ServerCall) (watch.ResumeMarker, error)
 pkg syncbase, type DatabaseServerMethods interface, GetSchemaMetadata(*context.T, rpc.ServerCall) (SchemaMetadata, error)
 pkg syncbase, type DatabaseServerMethods interface, GetSyncgroupMembers(*context.T, rpc.ServerCall, string) (map[string]SyncgroupMemberInfo, error)
@@ -586,17 +616,16 @@
 pkg syncbase, type DatabaseServerMethods interface, JoinSyncgroup(*context.T, rpc.ServerCall, string, SyncgroupMemberInfo) (SyncgroupSpec, error)
 pkg syncbase, type DatabaseServerMethods interface, KeepBlob(*context.T, rpc.ServerCall, BlobRef, uint64) error
 pkg syncbase, type DatabaseServerMethods interface, LeaveSyncgroup(*context.T, rpc.ServerCall, string) error
-pkg syncbase, type DatabaseServerMethods interface, ListTables(*context.T, rpc.ServerCall) ([]string, error)
+pkg syncbase, type DatabaseServerMethods interface, ListCollections(*context.T, rpc.ServerCall) ([]string, error)
 pkg syncbase, type DatabaseServerMethods interface, PauseSync(*context.T, rpc.ServerCall) error
 pkg syncbase, type DatabaseServerMethods interface, PinBlob(*context.T, rpc.ServerCall, BlobRef) error
 pkg syncbase, type DatabaseServerMethods interface, PutBlob(*context.T, BlobManagerPutBlobServerCall, BlobRef) error
 pkg syncbase, type DatabaseServerMethods interface, ResumeSync(*context.T, rpc.ServerCall) error
-pkg syncbase, type DatabaseServerMethods interface, SetPermissions(*context.T, rpc.ServerCall, access.Permissions, string) error
 pkg syncbase, type DatabaseServerMethods interface, SetSchemaMetadata(*context.T, rpc.ServerCall, SchemaMetadata) error
 pkg syncbase, type DatabaseServerMethods interface, SetSyncgroupSpec(*context.T, rpc.ServerCall, string, SyncgroupSpec, string) error
 pkg syncbase, type DatabaseServerMethods interface, StartConflictResolver(*context.T, ConflictManagerStartConflictResolverServerCall) error
 pkg syncbase, type DatabaseServerMethods interface, UnpinBlob(*context.T, rpc.ServerCall, BlobRef) error
-pkg syncbase, type DatabaseServerMethods interface, WatchGlob(*context.T, GlobWatcherWatchGlobServerCall, GlobRequest) error
+pkg syncbase, type DatabaseServerMethods interface, unexported methods
 pkg syncbase, type DatabaseServerStub interface, Abort(*context.T, rpc.ServerCall, int32) error
 pkg syncbase, type DatabaseServerStub interface, BeginBatch(*context.T, rpc.ServerCall, int32, BatchOptions) (string, error)
 pkg syncbase, type DatabaseServerStub interface, Commit(*context.T, rpc.ServerCall, int32) error
@@ -613,14 +642,13 @@
 pkg syncbase, type DatabaseServerStub interface, GetBlobSize(*context.T, rpc.ServerCall, BlobRef) (int64, error)
 pkg syncbase, type DatabaseServerStub interface, GetResumeMarker(*context.T, rpc.ServerCall) (watch.ResumeMarker, error)
 pkg syncbase, type DatabaseServerStub interface, KeepBlob(*context.T, rpc.ServerCall, BlobRef, uint64) error
-pkg syncbase, type DatabaseServerStub interface, ListTables(*context.T, rpc.ServerCall) ([]string, error)
+pkg syncbase, type DatabaseServerStub interface, ListCollections(*context.T, rpc.ServerCall) ([]string, error)
 pkg syncbase, type DatabaseServerStub interface, PauseSync(*context.T, rpc.ServerCall) error
 pkg syncbase, type DatabaseServerStub interface, PinBlob(*context.T, rpc.ServerCall, BlobRef) error
 pkg syncbase, type DatabaseServerStub interface, PutBlob(*context.T, *BlobManagerPutBlobServerCallStub, BlobRef) error
 pkg syncbase, type DatabaseServerStub interface, ResumeSync(*context.T, rpc.ServerCall) error
 pkg syncbase, type DatabaseServerStub interface, StartConflictResolver(*context.T, *ConflictManagerStartConflictResolverServerCallStub) error
 pkg syncbase, type DatabaseServerStub interface, UnpinBlob(*context.T, rpc.ServerCall, BlobRef) error
-pkg syncbase, type DatabaseServerStub interface, WatchGlob(*context.T, *GlobWatcherWatchGlobServerCallStub, GlobRequest) error
 pkg syncbase, type DatabaseServerStub interface, unexported methods
 pkg syncbase, type DatabaseServerStubMethods interface, Abort(*context.T, rpc.ServerCall, int32) error
 pkg syncbase, type DatabaseServerStubMethods interface, BeginBatch(*context.T, rpc.ServerCall, int32, BatchOptions) (string, error)
@@ -637,31 +665,25 @@
 pkg syncbase, type DatabaseServerStubMethods interface, GetBlobSize(*context.T, rpc.ServerCall, BlobRef) (int64, error)
 pkg syncbase, type DatabaseServerStubMethods interface, GetResumeMarker(*context.T, rpc.ServerCall) (watch.ResumeMarker, error)
 pkg syncbase, type DatabaseServerStubMethods interface, KeepBlob(*context.T, rpc.ServerCall, BlobRef, uint64) error
-pkg syncbase, type DatabaseServerStubMethods interface, ListTables(*context.T, rpc.ServerCall) ([]string, error)
+pkg syncbase, type DatabaseServerStubMethods interface, ListCollections(*context.T, rpc.ServerCall) ([]string, error)
 pkg syncbase, type DatabaseServerStubMethods interface, PauseSync(*context.T, rpc.ServerCall) error
 pkg syncbase, type DatabaseServerStubMethods interface, PinBlob(*context.T, rpc.ServerCall, BlobRef) error
 pkg syncbase, type DatabaseServerStubMethods interface, PutBlob(*context.T, *BlobManagerPutBlobServerCallStub, BlobRef) error
 pkg syncbase, type DatabaseServerStubMethods interface, ResumeSync(*context.T, rpc.ServerCall) error
 pkg syncbase, type DatabaseServerStubMethods interface, StartConflictResolver(*context.T, *ConflictManagerStartConflictResolverServerCallStub) error
 pkg syncbase, type DatabaseServerStubMethods interface, UnpinBlob(*context.T, rpc.ServerCall, BlobRef) error
-pkg syncbase, type DatabaseServerStubMethods interface, WatchGlob(*context.T, *GlobWatcherWatchGlobServerCallStub, GlobRequest) error
 pkg syncbase, type DatabaseServerStubMethods interface, unexported methods
-pkg syncbase, type DatabaseWatcherClientMethods interface { GetResumeMarker, WatchGlob }
 pkg syncbase, type DatabaseWatcherClientMethods interface, GetResumeMarker(*context.T, ...rpc.CallOpt) (watch.ResumeMarker, error)
-pkg syncbase, type DatabaseWatcherClientMethods interface, WatchGlob(*context.T, GlobRequest, ...rpc.CallOpt) (GlobWatcherWatchGlobClientCall, error)
-pkg syncbase, type DatabaseWatcherClientStub interface { GetResumeMarker, WatchGlob }
+pkg syncbase, type DatabaseWatcherClientMethods interface, unexported methods
 pkg syncbase, type DatabaseWatcherClientStub interface, GetResumeMarker(*context.T, ...rpc.CallOpt) (watch.ResumeMarker, error)
-pkg syncbase, type DatabaseWatcherClientStub interface, WatchGlob(*context.T, GlobRequest, ...rpc.CallOpt) (GlobWatcherWatchGlobClientCall, error)
-pkg syncbase, type DatabaseWatcherServerMethods interface { GetResumeMarker, WatchGlob }
+pkg syncbase, type DatabaseWatcherClientStub interface, unexported methods
 pkg syncbase, type DatabaseWatcherServerMethods interface, GetResumeMarker(*context.T, rpc.ServerCall) (watch.ResumeMarker, error)
-pkg syncbase, type DatabaseWatcherServerMethods interface, WatchGlob(*context.T, GlobWatcherWatchGlobServerCall, GlobRequest) error
-pkg syncbase, type DatabaseWatcherServerStub interface { Describe__, GetResumeMarker, WatchGlob }
+pkg syncbase, type DatabaseWatcherServerMethods interface, unexported methods
 pkg syncbase, type DatabaseWatcherServerStub interface, Describe__() []rpc.InterfaceDesc
 pkg syncbase, type DatabaseWatcherServerStub interface, GetResumeMarker(*context.T, rpc.ServerCall) (watch.ResumeMarker, error)
-pkg syncbase, type DatabaseWatcherServerStub interface, WatchGlob(*context.T, *GlobWatcherWatchGlobServerCallStub, GlobRequest) error
-pkg syncbase, type DatabaseWatcherServerStubMethods interface { GetResumeMarker, WatchGlob }
+pkg syncbase, type DatabaseWatcherServerStub interface, unexported methods
 pkg syncbase, type DatabaseWatcherServerStubMethods interface, GetResumeMarker(*context.T, rpc.ServerCall) (watch.ResumeMarker, error)
-pkg syncbase, type DatabaseWatcherServerStubMethods interface, WatchGlob(*context.T, *GlobWatcherWatchGlobServerCallStub, GlobRequest) error
+pkg syncbase, type DatabaseWatcherServerStubMethods interface, unexported methods
 pkg syncbase, type DevModeUpdateVClockOpts struct
 pkg syncbase, type DevModeUpdateVClockOpts struct, DoLocalUpdate bool
 pkg syncbase, type DevModeUpdateVClockOpts struct, DoNtpUpdate bool
@@ -719,11 +741,11 @@
 pkg syncbase, type RowClientMethods interface, Exists(*context.T, int32, ...rpc.CallOpt) (bool, error)
 pkg syncbase, type RowClientMethods interface, Get(*context.T, int32, ...rpc.CallOpt) ([]byte, error)
 pkg syncbase, type RowClientMethods interface, Put(*context.T, int32, []byte, ...rpc.CallOpt) error
-pkg syncbase, type RowClientStub interface { Delete, Exists, Get, Put }
 pkg syncbase, type RowClientStub interface, Delete(*context.T, int32, ...rpc.CallOpt) error
 pkg syncbase, type RowClientStub interface, Exists(*context.T, int32, ...rpc.CallOpt) (bool, error)
 pkg syncbase, type RowClientStub interface, Get(*context.T, int32, ...rpc.CallOpt) ([]byte, error)
 pkg syncbase, type RowClientStub interface, Put(*context.T, int32, []byte, ...rpc.CallOpt) error
+pkg syncbase, type RowClientStub interface, unexported methods
 pkg syncbase, type RowInfo struct
 pkg syncbase, type RowInfo struct, BatchIds []uint64
 pkg syncbase, type RowInfo struct, Op Operation
@@ -758,9 +780,9 @@
 pkg syncbase, type SchemaManagerClientMethods interface { GetSchemaMetadata, SetSchemaMetadata }
 pkg syncbase, type SchemaManagerClientMethods interface, GetSchemaMetadata(*context.T, ...rpc.CallOpt) (SchemaMetadata, error)
 pkg syncbase, type SchemaManagerClientMethods interface, SetSchemaMetadata(*context.T, SchemaMetadata, ...rpc.CallOpt) error
-pkg syncbase, type SchemaManagerClientStub interface { GetSchemaMetadata, SetSchemaMetadata }
 pkg syncbase, type SchemaManagerClientStub interface, GetSchemaMetadata(*context.T, ...rpc.CallOpt) (SchemaMetadata, error)
 pkg syncbase, type SchemaManagerClientStub interface, SetSchemaMetadata(*context.T, SchemaMetadata, ...rpc.CallOpt) error
+pkg syncbase, type SchemaManagerClientStub interface, unexported methods
 pkg syncbase, type SchemaManagerServerMethods interface { GetSchemaMetadata, SetSchemaMetadata }
 pkg syncbase, type SchemaManagerServerMethods interface, GetSchemaMetadata(*context.T, rpc.ServerCall) (SchemaMetadata, error)
 pkg syncbase, type SchemaManagerServerMethods interface, SetSchemaMetadata(*context.T, rpc.ServerCall, SchemaMetadata) error
@@ -774,21 +796,15 @@
 pkg syncbase, type SchemaMetadataTarget struct, Value *SchemaMetadata
 pkg syncbase, type SchemaMetadataTarget struct, embedded vdl.FieldsTargetBase
 pkg syncbase, type SchemaMetadataTarget struct, embedded vdl.TargetBase
-pkg syncbase, type ServiceClientMethods interface { DevModeGetTime, DevModeUpdateVClock, GetPermissions, SetPermissions }
 pkg syncbase, type ServiceClientMethods interface, DevModeGetTime(*context.T, ...rpc.CallOpt) (time.Time, error)
 pkg syncbase, type ServiceClientMethods interface, DevModeUpdateVClock(*context.T, DevModeUpdateVClockOpts, ...rpc.CallOpt) error
-pkg syncbase, type ServiceClientMethods interface, GetPermissions(*context.T, ...rpc.CallOpt) (access.Permissions, string, error)
-pkg syncbase, type ServiceClientMethods interface, SetPermissions(*context.T, access.Permissions, string, ...rpc.CallOpt) error
-pkg syncbase, type ServiceClientStub interface { DevModeGetTime, DevModeUpdateVClock, GetPermissions, SetPermissions }
+pkg syncbase, type ServiceClientMethods interface, unexported methods
 pkg syncbase, type ServiceClientStub interface, DevModeGetTime(*context.T, ...rpc.CallOpt) (time.Time, error)
 pkg syncbase, type ServiceClientStub interface, DevModeUpdateVClock(*context.T, DevModeUpdateVClockOpts, ...rpc.CallOpt) error
-pkg syncbase, type ServiceClientStub interface, GetPermissions(*context.T, ...rpc.CallOpt) (access.Permissions, string, error)
-pkg syncbase, type ServiceClientStub interface, SetPermissions(*context.T, access.Permissions, string, ...rpc.CallOpt) error
-pkg syncbase, type ServiceServerMethods interface { DevModeGetTime, DevModeUpdateVClock, GetPermissions, SetPermissions }
+pkg syncbase, type ServiceClientStub interface, unexported methods
 pkg syncbase, type ServiceServerMethods interface, DevModeGetTime(*context.T, rpc.ServerCall) (time.Time, error)
 pkg syncbase, type ServiceServerMethods interface, DevModeUpdateVClock(*context.T, rpc.ServerCall, DevModeUpdateVClockOpts) error
-pkg syncbase, type ServiceServerMethods interface, GetPermissions(*context.T, rpc.ServerCall) (access.Permissions, string, error)
-pkg syncbase, type ServiceServerMethods interface, SetPermissions(*context.T, rpc.ServerCall, access.Permissions, string) error
+pkg syncbase, type ServiceServerMethods interface, unexported methods
 pkg syncbase, type ServiceServerStub interface, Describe__() []rpc.InterfaceDesc
 pkg syncbase, type ServiceServerStub interface, unexported methods
 pkg syncbase, type ServiceServerStubMethods ServiceServerMethods
@@ -809,7 +825,6 @@
 pkg syncbase, type SyncgroupManagerClientMethods interface, JoinSyncgroup(*context.T, string, SyncgroupMemberInfo, ...rpc.CallOpt) (SyncgroupSpec, error)
 pkg syncbase, type SyncgroupManagerClientMethods interface, LeaveSyncgroup(*context.T, string, ...rpc.CallOpt) error
 pkg syncbase, type SyncgroupManagerClientMethods interface, SetSyncgroupSpec(*context.T, string, SyncgroupSpec, string, ...rpc.CallOpt) error
-pkg syncbase, type SyncgroupManagerClientStub interface { CreateSyncgroup, DestroySyncgroup, EjectFromSyncgroup, GetSyncgroupMembers, GetSyncgroupNames, GetSyncgroupSpec, JoinSyncgroup, LeaveSyncgroup, SetSyncgroupSpec }
 pkg syncbase, type SyncgroupManagerClientStub interface, CreateSyncgroup(*context.T, string, SyncgroupSpec, SyncgroupMemberInfo, ...rpc.CallOpt) error
 pkg syncbase, type SyncgroupManagerClientStub interface, DestroySyncgroup(*context.T, string, ...rpc.CallOpt) error
 pkg syncbase, type SyncgroupManagerClientStub interface, EjectFromSyncgroup(*context.T, string, string, ...rpc.CallOpt) error
@@ -819,6 +834,7 @@
 pkg syncbase, type SyncgroupManagerClientStub interface, JoinSyncgroup(*context.T, string, SyncgroupMemberInfo, ...rpc.CallOpt) (SyncgroupSpec, error)
 pkg syncbase, type SyncgroupManagerClientStub interface, LeaveSyncgroup(*context.T, string, ...rpc.CallOpt) error
 pkg syncbase, type SyncgroupManagerClientStub interface, SetSyncgroupSpec(*context.T, string, SyncgroupSpec, string, ...rpc.CallOpt) error
+pkg syncbase, type SyncgroupManagerClientStub interface, unexported methods
 pkg syncbase, type SyncgroupManagerServerMethods interface { CreateSyncgroup, DestroySyncgroup, EjectFromSyncgroup, GetSyncgroupMembers, GetSyncgroupNames, GetSyncgroupSpec, JoinSyncgroup, LeaveSyncgroup, SetSyncgroupSpec }
 pkg syncbase, type SyncgroupManagerServerMethods interface, CreateSyncgroup(*context.T, rpc.ServerCall, string, SyncgroupSpec, SyncgroupMemberInfo) error
 pkg syncbase, type SyncgroupManagerServerMethods interface, DestroySyncgroup(*context.T, rpc.ServerCall, string) error
@@ -844,91 +860,11 @@
 pkg syncbase, type SyncgroupSpec struct, IsPrivate bool
 pkg syncbase, type SyncgroupSpec struct, MountTables []string
 pkg syncbase, type SyncgroupSpec struct, Perms access.Permissions
-pkg syncbase, type SyncgroupSpec struct, Prefixes []TableRow
+pkg syncbase, type SyncgroupSpec struct, Prefixes []CollectionRow
 pkg syncbase, type SyncgroupSpecTarget struct
 pkg syncbase, type SyncgroupSpecTarget struct, Value *SyncgroupSpec
 pkg syncbase, type SyncgroupSpecTarget struct, embedded vdl.FieldsTargetBase
 pkg syncbase, type SyncgroupSpecTarget struct, embedded vdl.TargetBase
-pkg syncbase, type TableClientMethods interface { Create, DeletePrefixPermissions, DeleteRange, Destroy, Exists, GetPermissions, GetPrefixPermissions, Scan, SetPermissions, SetPrefixPermissions }
-pkg syncbase, type TableClientMethods interface, Create(*context.T, int32, access.Permissions, ...rpc.CallOpt) error
-pkg syncbase, type TableClientMethods interface, DeletePrefixPermissions(*context.T, int32, string, ...rpc.CallOpt) error
-pkg syncbase, type TableClientMethods interface, DeleteRange(*context.T, int32, []byte, []byte, ...rpc.CallOpt) error
-pkg syncbase, type TableClientMethods interface, Destroy(*context.T, int32, ...rpc.CallOpt) error
-pkg syncbase, type TableClientMethods interface, Exists(*context.T, int32, ...rpc.CallOpt) (bool, error)
-pkg syncbase, type TableClientMethods interface, GetPermissions(*context.T, int32, ...rpc.CallOpt) (access.Permissions, error)
-pkg syncbase, type TableClientMethods interface, GetPrefixPermissions(*context.T, int32, string, ...rpc.CallOpt) ([]PrefixPermissions, error)
-pkg syncbase, type TableClientMethods interface, Scan(*context.T, int32, []byte, []byte, ...rpc.CallOpt) (TableScanClientCall, error)
-pkg syncbase, type TableClientMethods interface, SetPermissions(*context.T, int32, access.Permissions, ...rpc.CallOpt) error
-pkg syncbase, type TableClientMethods interface, SetPrefixPermissions(*context.T, int32, string, access.Permissions, ...rpc.CallOpt) error
-pkg syncbase, type TableClientStub interface { Create, DeletePrefixPermissions, DeleteRange, Destroy, Exists, GetPermissions, GetPrefixPermissions, Scan, SetPermissions, SetPrefixPermissions }
-pkg syncbase, type TableClientStub interface, Create(*context.T, int32, access.Permissions, ...rpc.CallOpt) error
-pkg syncbase, type TableClientStub interface, DeletePrefixPermissions(*context.T, int32, string, ...rpc.CallOpt) error
-pkg syncbase, type TableClientStub interface, DeleteRange(*context.T, int32, []byte, []byte, ...rpc.CallOpt) error
-pkg syncbase, type TableClientStub interface, Destroy(*context.T, int32, ...rpc.CallOpt) error
-pkg syncbase, type TableClientStub interface, Exists(*context.T, int32, ...rpc.CallOpt) (bool, error)
-pkg syncbase, type TableClientStub interface, GetPermissions(*context.T, int32, ...rpc.CallOpt) (access.Permissions, error)
-pkg syncbase, type TableClientStub interface, GetPrefixPermissions(*context.T, int32, string, ...rpc.CallOpt) ([]PrefixPermissions, error)
-pkg syncbase, type TableClientStub interface, Scan(*context.T, int32, []byte, []byte, ...rpc.CallOpt) (TableScanClientCall, error)
-pkg syncbase, type TableClientStub interface, SetPermissions(*context.T, int32, access.Permissions, ...rpc.CallOpt) error
-pkg syncbase, type TableClientStub interface, SetPrefixPermissions(*context.T, int32, string, access.Permissions, ...rpc.CallOpt) error
-pkg syncbase, type TableRow struct
-pkg syncbase, type TableRow struct, Row string
-pkg syncbase, type TableRow struct, TableName string
-pkg syncbase, type TableRowTarget struct
-pkg syncbase, type TableRowTarget struct, Value *TableRow
-pkg syncbase, type TableRowTarget struct, embedded vdl.FieldsTargetBase
-pkg syncbase, type TableRowTarget struct, embedded vdl.TargetBase
-pkg syncbase, type TableScanClientCall interface { Finish, RecvStream }
-pkg syncbase, type TableScanClientCall interface, Finish() error
-pkg syncbase, type TableScanClientCall interface, RecvStream() interface {  Advance() bool;; Value() KeyValue;; Err() error;}
-pkg syncbase, type TableScanClientStream interface { RecvStream }
-pkg syncbase, type TableScanClientStream interface, RecvStream() interface {  Advance() bool;; Value() KeyValue;; Err() error;}
-pkg syncbase, type TableScanServerCall interface { GrantedBlessings, LocalEndpoint, RemoteEndpoint, Security, SendStream, Server, Suffix }
-pkg syncbase, type TableScanServerCall interface, GrantedBlessings() security.Blessings
-pkg syncbase, type TableScanServerCall interface, LocalEndpoint() naming.Endpoint
-pkg syncbase, type TableScanServerCall interface, RemoteEndpoint() naming.Endpoint
-pkg syncbase, type TableScanServerCall interface, Security() security.Call
-pkg syncbase, type TableScanServerCall interface, SendStream() interface {  Send(item KeyValue) error;}
-pkg syncbase, type TableScanServerCall interface, Server() Server
-pkg syncbase, type TableScanServerCall interface, Suffix() string
-pkg syncbase, type TableScanServerCallStub struct
-pkg syncbase, type TableScanServerCallStub struct, embedded rpc.StreamServerCall
-pkg syncbase, type TableScanServerStream interface { SendStream }
-pkg syncbase, type TableScanServerStream interface, SendStream() interface {  Send(item KeyValue) error;}
-pkg syncbase, type TableServerMethods interface { Create, DeletePrefixPermissions, DeleteRange, Destroy, Exists, GetPermissions, GetPrefixPermissions, Scan, SetPermissions, SetPrefixPermissions }
-pkg syncbase, type TableServerMethods interface, Create(*context.T, rpc.ServerCall, int32, access.Permissions) error
-pkg syncbase, type TableServerMethods interface, DeletePrefixPermissions(*context.T, rpc.ServerCall, int32, string) error
-pkg syncbase, type TableServerMethods interface, DeleteRange(*context.T, rpc.ServerCall, int32, []byte, []byte) error
-pkg syncbase, type TableServerMethods interface, Destroy(*context.T, rpc.ServerCall, int32) error
-pkg syncbase, type TableServerMethods interface, Exists(*context.T, rpc.ServerCall, int32) (bool, error)
-pkg syncbase, type TableServerMethods interface, GetPermissions(*context.T, rpc.ServerCall, int32) (access.Permissions, error)
-pkg syncbase, type TableServerMethods interface, GetPrefixPermissions(*context.T, rpc.ServerCall, int32, string) ([]PrefixPermissions, error)
-pkg syncbase, type TableServerMethods interface, Scan(*context.T, TableScanServerCall, int32, []byte, []byte) error
-pkg syncbase, type TableServerMethods interface, SetPermissions(*context.T, rpc.ServerCall, int32, access.Permissions) error
-pkg syncbase, type TableServerMethods interface, SetPrefixPermissions(*context.T, rpc.ServerCall, int32, string, access.Permissions) error
-pkg syncbase, type TableServerStub interface { Create, DeletePrefixPermissions, DeleteRange, Describe__, Destroy, Exists, GetPermissions, GetPrefixPermissions, Scan, SetPermissions, SetPrefixPermissions }
-pkg syncbase, type TableServerStub interface, Create(*context.T, rpc.ServerCall, int32, access.Permissions) error
-pkg syncbase, type TableServerStub interface, DeletePrefixPermissions(*context.T, rpc.ServerCall, int32, string) error
-pkg syncbase, type TableServerStub interface, DeleteRange(*context.T, rpc.ServerCall, int32, []byte, []byte) error
-pkg syncbase, type TableServerStub interface, Describe__() []rpc.InterfaceDesc
-pkg syncbase, type TableServerStub interface, Destroy(*context.T, rpc.ServerCall, int32) error
-pkg syncbase, type TableServerStub interface, Exists(*context.T, rpc.ServerCall, int32) (bool, error)
-pkg syncbase, type TableServerStub interface, GetPermissions(*context.T, rpc.ServerCall, int32) (access.Permissions, error)
-pkg syncbase, type TableServerStub interface, GetPrefixPermissions(*context.T, rpc.ServerCall, int32, string) ([]PrefixPermissions, error)
-pkg syncbase, type TableServerStub interface, Scan(*context.T, *TableScanServerCallStub, int32, []byte, []byte) error
-pkg syncbase, type TableServerStub interface, SetPermissions(*context.T, rpc.ServerCall, int32, access.Permissions) error
-pkg syncbase, type TableServerStub interface, SetPrefixPermissions(*context.T, rpc.ServerCall, int32, string, access.Permissions) error
-pkg syncbase, type TableServerStubMethods interface { Create, DeletePrefixPermissions, DeleteRange, Destroy, Exists, GetPermissions, GetPrefixPermissions, Scan, SetPermissions, SetPrefixPermissions }
-pkg syncbase, type TableServerStubMethods interface, Create(*context.T, rpc.ServerCall, int32, access.Permissions) error
-pkg syncbase, type TableServerStubMethods interface, DeletePrefixPermissions(*context.T, rpc.ServerCall, int32, string) error
-pkg syncbase, type TableServerStubMethods interface, DeleteRange(*context.T, rpc.ServerCall, int32, []byte, []byte) error
-pkg syncbase, type TableServerStubMethods interface, Destroy(*context.T, rpc.ServerCall, int32) error
-pkg syncbase, type TableServerStubMethods interface, Exists(*context.T, rpc.ServerCall, int32) (bool, error)
-pkg syncbase, type TableServerStubMethods interface, GetPermissions(*context.T, rpc.ServerCall, int32) (access.Permissions, error)
-pkg syncbase, type TableServerStubMethods interface, GetPrefixPermissions(*context.T, rpc.ServerCall, int32, string) ([]PrefixPermissions, error)
-pkg syncbase, type TableServerStubMethods interface, Scan(*context.T, *TableScanServerCallStub, int32, []byte, []byte) error
-pkg syncbase, type TableServerStubMethods interface, SetPermissions(*context.T, rpc.ServerCall, int32, access.Permissions) error
-pkg syncbase, type TableServerStubMethods interface, SetPrefixPermissions(*context.T, rpc.ServerCall, int32, string, access.Permissions) error
 pkg syncbase, type Value struct
 pkg syncbase, type Value struct, Bytes []byte
 pkg syncbase, type Value struct, State ValueState
@@ -949,25 +885,25 @@
 pkg syncbase, var BatchSourceAll [...]BatchSource
 pkg syncbase, var BlobFetchStateAll [...]BlobFetchState
 pkg syncbase, var BlobManagerDesc rpc.InterfaceDesc
+pkg syncbase, var CollectionDesc rpc.InterfaceDesc
 pkg syncbase, var ConflictManagerDesc rpc.InterfaceDesc
 pkg syncbase, var DatabaseDesc rpc.InterfaceDesc
 pkg syncbase, var DatabaseWatcherDesc rpc.InterfaceDesc
-pkg syncbase, var ErrBlobNotCommitted verror.IDAction
-pkg syncbase, var ErrBoundToBatch verror.IDAction
-pkg syncbase, var ErrConcurrentBatch verror.IDAction
-pkg syncbase, var ErrCorruptDatabase verror.IDAction
-pkg syncbase, var ErrInvalidName verror.IDAction
-pkg syncbase, var ErrNotBoundToBatch verror.IDAction
-pkg syncbase, var ErrNotInDevMode verror.IDAction
-pkg syncbase, var ErrReadOnlyBatch verror.IDAction
-pkg syncbase, var ErrSchemaVersionMismatch verror.IDAction
-pkg syncbase, var ErrSyncgroupJoinFailed verror.IDAction
-pkg syncbase, var ErrUnknownBatch verror.IDAction
+pkg syncbase, var ErrBlobNotCommitted unknown-type
+pkg syncbase, var ErrBoundToBatch unknown-type
+pkg syncbase, var ErrConcurrentBatch unknown-type
+pkg syncbase, var ErrCorruptDatabase unknown-type
+pkg syncbase, var ErrInvalidName unknown-type
+pkg syncbase, var ErrNotBoundToBatch unknown-type
+pkg syncbase, var ErrNotInDevMode unknown-type
+pkg syncbase, var ErrReadOnlyBatch unknown-type
+pkg syncbase, var ErrSchemaVersionMismatch unknown-type
+pkg syncbase, var ErrSyncgroupJoinFailed unknown-type
+pkg syncbase, var ErrUnknownBatch unknown-type
 pkg syncbase, var ResolverTypeAll [...]ResolverType
 pkg syncbase, var RowDesc rpc.InterfaceDesc
 pkg syncbase, var SchemaManagerDesc rpc.InterfaceDesc
 pkg syncbase, var ServiceDesc rpc.InterfaceDesc
 pkg syncbase, var SyncgroupManagerDesc rpc.InterfaceDesc
-pkg syncbase, var TableDesc rpc.InterfaceDesc
 pkg syncbase, var ValueSelectionAll [...]ValueSelection
 pkg syncbase, var ValueStateAll [...]ValueState
diff --git a/services/syncbase/service.vdl b/services/syncbase/service.vdl
index 72a32fb..7ca656b 100644
--- a/services/syncbase/service.vdl
+++ b/services/syncbase/service.vdl
@@ -59,9 +59,9 @@
 	permissions.Object
 }
 
-// Database represents a collection of Tables. Batches, queries, sync, watch,
-// etc. all operate at the Database level.
-// Database.Glob operates over Table names.
+// Database represents a set of Collections. Batches, queries, sync, watch, etc.
+// all operate at the Database level.
+// Database.Glob operates over Collection names.
 // Param schemaVersion is the version number that the client expects the
 // database to be at. To disable schema version checking, pass -1.
 type Database interface {
@@ -79,7 +79,7 @@
 	// do not exist.
 	Exists(schemaVersion int32) (bool | error) {access.Resolve}
 
-	// ListTables returns a list of all Table names.
+	// ListCollections returns a list of all Collection names.
 	// This method exists on Database but not on Service or App because for the
 	// latter we can simply use glob, while for the former glob fails on
 	// BatchDatabase since we encode the batch id in the BatchDatabase object
@@ -92,7 +92,7 @@
 	//    results. This is inefficient in general, and broken for us since
 	//    Glob("app/*") does not return batch database names like "a/d##bId".
 	// TODO(sadovsky): Maybe switch to streaming RPC.
-	ListTables() ([]string | error) {access.Read}
+	ListCollections() ([]string | error) {access.Read}
 
 	// Exec executes a syncQL query with positional parameters and returns all
 	// results as specified by the query's select/delete statement.
@@ -153,28 +153,28 @@
 	ConflictManager
 }
 
-// Table represents a collection of Rows.
-// Table.Glob operates over the primary keys of Rows in the Table.
+// Collection represents a collection of Rows.
+// Collection.Glob operates over the primary keys of Rows in the Collection.
 // SchemaVersion is the version number that the client expects the database
 // to be at. To disable schema version checking, pass -1.
-type Table interface {
-	// Create creates this Table.
+type Collection interface {
+	// Create creates this Collection.
 	// If perms is nil, we inherit (copy) the Database perms.
 	Create(schemaVersion int32, perms access.Permissions) error {access.Write}
 
-	// Destroy destroys this Table.
+	// Destroy destroys this Collection.
 	Destroy(schemaVersion int32) error {access.Write}
 
-	// Exists returns true only if this Table exists. Insufficient permissions
-	// cause Exists to return false instead of an error.
+	// Exists returns true only if this Collection exists. Insufficient
+	// permissions cause Exists to return false instead of an error.
 	// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy
 	// do not exist.
 	Exists(schemaVersion int32) (bool | error) {access.Resolve}
 
-	// GetPermissions returns the current Permissions for the Table.
+	// GetPermissions returns the current Permissions for the Collection.
 	GetPermissions(schemaVersion int32) (access.Permissions | error) {access.Admin}
 
-	// SetPermissions replaces the current Permissions for the Table.
+	// SetPermissions replaces the current Permissions for the Collection.
 	SetPermissions(schemaVersion int32, perms access.Permissions) error {access.Admin}
 
 	// DeleteRange deletes all rows in the given half-open range [start, limit).
@@ -188,11 +188,11 @@
 	// documented in model.go.
 	Scan(schemaVersion int32, start, limit []byte) stream<_, KeyValue> error {access.Read}
 
-	// GetPrefixPermissions returns an array of (prefix, perms) pairs. The array is
-	// sorted from longest prefix to shortest, so element zero is the one that
+	// GetPrefixPermissions returns an array of (prefix, perms) pairs. The array
+	// is sorted from longest prefix to shortest, so element zero is the one that
 	// applies to the row with the given key. The last element is always the
-	// prefix "" which represents the table's permissions -- the array will always
-	// have at least one element.
+	// prefix "" which represents the collection's permissions -- the array will
+	// always have at least one element.
 	GetPrefixPermissions(schemaVersion int32, key string) ([]PrefixPermissions | error) {access.Admin}
 
 	// SetPrefixPermissions sets the permissions for all current and future rows with
@@ -210,9 +210,9 @@
 	DeletePrefixPermissions(schemaVersion int32, prefix string) error {access.Admin}
 }
 
-// Row represents a single row in a Table.
+// Row represents a single row in a Collection.
 // All access checks are performed against the most specific matching prefix
-// permissions in the Table.
+// permissions in the Collection.
 // SchemaVersion is the version number that the client expects the database
 // to be at. To disable schema version checking, pass -1.
 // NOTE(sadovsky): Currently we send []byte values over the wire for Get, Put,
@@ -408,7 +408,7 @@
 // without re-ordering. See watch.GlobWatcher for a detailed explanation of the
 // behavior.
 // TODO(rogulenko): Currently the only supported watch patterns are
-// "<tableName>/<rowPrefix>*". Consider changing that.
+// "<collectionName>/<rowPrefix>*". Consider changing that.
 //
 // Watching is done by starting a streaming RPC. The RPC takes a ResumeMarker
 // argument that points to a particular place in the database event log. If an
@@ -417,8 +417,8 @@
 // only changes since the provided ResumeMarker.
 //
 // The result stream consists of a never-ending sequence of Change messages
-// (until the call fails or is canceled). Each Change contains the Name field
-// in the form "<tableName>/<rowKey>" and the Value field of the StoreChange
+// (until the call fails or is canceled). Each Change contains the Name field in
+// the form "<collectionName>/<rowKey>" and the Value field of the StoreChange
 // type. If the client has no access to a row specified in a change, that change
 // is excluded from the result stream.
 //
diff --git a/services/syncbase/syncbase.vdl.go b/services/syncbase/syncbase.vdl.go
index 9a6edcd..22c6559 100644
--- a/services/syncbase/syncbase.vdl.go
+++ b/services/syncbase/syncbase.vdl.go
@@ -476,29 +476,29 @@
 	return nil
 }
 
-// TableRow encapsulates the table name and row key or row prefix.
-type TableRow struct {
-	TableName string
-	Row       string
+// CollectionRow encapsulates the collection name and row key or row prefix.
+type CollectionRow struct {
+	CollectionName string
+	Row            string
 }
 
-func (TableRow) __VDLReflect(struct {
-	Name string `vdl:"v.io/v23/services/syncbase.TableRow"`
+func (CollectionRow) __VDLReflect(struct {
+	Name string `vdl:"v.io/v23/services/syncbase.CollectionRow"`
 }) {
 }
 
-func (m *TableRow) FillVDLTarget(t vdl.Target, tt *vdl.Type) error {
+func (m *CollectionRow) FillVDLTarget(t vdl.Target, tt *vdl.Type) error {
 	fieldsTarget1, err := t.StartFields(tt)
 	if err != nil {
 		return err
 	}
 
-	keyTarget2, fieldTarget3, err := fieldsTarget1.StartField("TableName")
+	keyTarget2, fieldTarget3, err := fieldsTarget1.StartField("CollectionName")
 	if err != vdl.ErrFieldNoExist && err != nil {
 		return err
 	}
 	if err != vdl.ErrFieldNoExist {
-		if err := fieldTarget3.FromString(string(m.TableName), tt.NonOptional().Field(0).Type); err != nil {
+		if err := fieldTarget3.FromString(string(m.CollectionName), tt.NonOptional().Field(0).Type); err != nil {
 			return err
 		}
 		if err := fieldsTarget1.FinishField(keyTarget2, fieldTarget3); err != nil {
@@ -523,43 +523,43 @@
 	return nil
 }
 
-func (m *TableRow) MakeVDLTarget() vdl.Target {
-	return &TableRowTarget{Value: m}
+func (m *CollectionRow) MakeVDLTarget() vdl.Target {
+	return &CollectionRowTarget{Value: m}
 }
 
-type TableRowTarget struct {
-	Value           *TableRow
-	tableNameTarget vdl.StringTarget
-	rowTarget       vdl.StringTarget
+type CollectionRowTarget struct {
+	Value                *CollectionRow
+	collectionNameTarget vdl.StringTarget
+	rowTarget            vdl.StringTarget
 	vdl.TargetBase
 	vdl.FieldsTargetBase
 }
 
-func (t *TableRowTarget) StartFields(tt *vdl.Type) (vdl.FieldsTarget, error) {
+func (t *CollectionRowTarget) StartFields(tt *vdl.Type) (vdl.FieldsTarget, error) {
 
-	if ttWant := vdl.TypeOf((*TableRow)(nil)).Elem(); !vdl.Compatible(tt, ttWant) {
+	if ttWant := vdl.TypeOf((*CollectionRow)(nil)).Elem(); !vdl.Compatible(tt, ttWant) {
 		return nil, fmt.Errorf("type %v incompatible with %v", tt, ttWant)
 	}
 	return t, nil
 }
-func (t *TableRowTarget) StartField(name string) (key, field vdl.Target, _ error) {
+func (t *CollectionRowTarget) StartField(name string) (key, field vdl.Target, _ error) {
 	switch name {
-	case "TableName":
-		t.tableNameTarget.Value = &t.Value.TableName
-		target, err := &t.tableNameTarget, error(nil)
+	case "CollectionName":
+		t.collectionNameTarget.Value = &t.Value.CollectionName
+		target, err := &t.collectionNameTarget, error(nil)
 		return nil, target, err
 	case "Row":
 		t.rowTarget.Value = &t.Value.Row
 		target, err := &t.rowTarget, error(nil)
 		return nil, target, err
 	default:
-		return nil, nil, fmt.Errorf("field %s not in struct v.io/v23/services/syncbase.TableRow", name)
+		return nil, nil, fmt.Errorf("field %s not in struct v.io/v23/services/syncbase.CollectionRow", name)
 	}
 }
-func (t *TableRowTarget) FinishField(_, _ vdl.Target) error {
+func (t *CollectionRowTarget) FinishField(_, _ vdl.Target) error {
 	return nil
 }
-func (t *TableRowTarget) FinishFields(_ vdl.FieldsTarget) error {
+func (t *CollectionRowTarget) FinishFields(_ vdl.FieldsTarget) error {
 
 	return nil
 }
@@ -570,8 +570,8 @@
 	Description string
 	// Permissions governing access to this syncgroup.
 	Perms access.Permissions
-	// Data (tableName-rowPrefix pairs) covered by this syncgroup.
-	Prefixes []TableRow
+	// Data (collectionName-rowPrefix pairs) covered by this syncgroup.
+	Prefixes []CollectionRow
 	// Mount tables at which to advertise this syncgroup, for rendezvous purposes.
 	// (Note that in addition to these mount tables, Syncbase also uses
 	// network-neighborhood-based discovery for rendezvous.)
@@ -756,21 +756,21 @@
 	return nil
 }
 
-// []TableRow
+// []CollectionRow
 type __VDLTarget1_list struct {
-	Value      *[]TableRow
-	elemTarget TableRowTarget
+	Value      *[]CollectionRow
+	elemTarget CollectionRowTarget
 	vdl.TargetBase
 	vdl.ListTargetBase
 }
 
 func (t *__VDLTarget1_list) StartList(tt *vdl.Type, len int) (vdl.ListTarget, error) {
 
-	if ttWant := vdl.TypeOf((*[]TableRow)(nil)); !vdl.Compatible(tt, ttWant) {
+	if ttWant := vdl.TypeOf((*[]CollectionRow)(nil)); !vdl.Compatible(tt, ttWant) {
 		return nil, fmt.Errorf("type %v incompatible with %v", tt, ttWant)
 	}
 	if cap(*t.Value) < len {
-		*t.Value = make([]TableRow, len)
+		*t.Value = make([]CollectionRow, len)
 	} else {
 		*t.Value = (*t.Value)[:len]
 	}
@@ -2495,10 +2495,10 @@
 // CrRule provides a filter and the type of resolution to perform for a row
 // under conflict that passes the filter.
 type CrRule struct {
-	// TableName is the name of the table that this rule applies to.
-	TableName string
-	// KeyPrefix represents the set of keys within the given table for which
-	// this policy applies. TableName must not be empty if this field is set.
+	// CollectionName is the name of the collection that this rule applies to.
+	CollectionName string
+	// KeyPrefix represents the set of keys within the given collection for which
+	// this policy applies. CollectionName must not be empty if this field is set.
 	KeyPrefix string
 	// Type includes the full package path for the value type for which this
 	// policy applies.
@@ -2518,12 +2518,12 @@
 		return err
 	}
 
-	keyTarget2, fieldTarget3, err := fieldsTarget1.StartField("TableName")
+	keyTarget2, fieldTarget3, err := fieldsTarget1.StartField("CollectionName")
 	if err != vdl.ErrFieldNoExist && err != nil {
 		return err
 	}
 	if err != vdl.ErrFieldNoExist {
-		if err := fieldTarget3.FromString(string(m.TableName), tt.NonOptional().Field(0).Type); err != nil {
+		if err := fieldTarget3.FromString(string(m.CollectionName), tt.NonOptional().Field(0).Type); err != nil {
 			return err
 		}
 		if err := fieldsTarget1.FinishField(keyTarget2, fieldTarget3); err != nil {
@@ -2578,11 +2578,11 @@
 }
 
 type CrRuleTarget struct {
-	Value           *CrRule
-	tableNameTarget vdl.StringTarget
-	keyPrefixTarget vdl.StringTarget
-	typeTarget      vdl.StringTarget
-	resolverTarget  ResolverTypeTarget
+	Value                *CrRule
+	collectionNameTarget vdl.StringTarget
+	keyPrefixTarget      vdl.StringTarget
+	typeTarget           vdl.StringTarget
+	resolverTarget       ResolverTypeTarget
 	vdl.TargetBase
 	vdl.FieldsTargetBase
 }
@@ -2596,9 +2596,9 @@
 }
 func (t *CrRuleTarget) StartField(name string) (key, field vdl.Target, _ error) {
 	switch name {
-	case "TableName":
-		t.tableNameTarget.Value = &t.Value.TableName
-		target, err := &t.tableNameTarget, error(nil)
+	case "CollectionName":
+		t.collectionNameTarget.Value = &t.Value.CollectionName
+		target, err := &t.collectionNameTarget, error(nil)
 		return nil, target, err
 	case "KeyPrefix":
 		t.keyPrefixTarget.Value = &t.Value.KeyPrefix
@@ -3182,7 +3182,7 @@
 	__VDLZeroBatchOptions            = BatchOptions{}
 	__VDLZeroPrefixPermissions       = PrefixPermissions{}
 	__VDLZeroKeyValue                = KeyValue{}
-	__VDLZeroTableRow                = TableRow{}
+	__VDLZeroCollectionRow           = CollectionRow{}
 	__VDLZeroSyncgroupSpec           = SyncgroupSpec{}
 	__VDLZeroSyncgroupMemberInfo     = SyncgroupMemberInfo{}
 	__VDLZeroResolverType            = ResolverTypeLastWins
@@ -3780,7 +3780,7 @@
 // without re-ordering. See watch.GlobWatcher for a detailed explanation of the
 // behavior.
 // TODO(rogulenko): Currently the only supported watch patterns are
-// "<tableName>/<rowPrefix>*". Consider changing that.
+// "<collectionName>/<rowPrefix>*". Consider changing that.
 //
 // Watching is done by starting a streaming RPC. The RPC takes a ResumeMarker
 // argument that points to a particular place in the database event log. If an
@@ -3789,8 +3789,8 @@
 // only changes since the provided ResumeMarker.
 //
 // The result stream consists of a never-ending sequence of Change messages
-// (until the call fails or is canceled). Each Change contains the Name field
-// in the form "<tableName>/<rowKey>" and the Value field of the StoreChange
+// (until the call fails or is canceled). Each Change contains the Name field in
+// the form "<collectionName>/<rowKey>" and the Value field of the StoreChange
 // type. If the client has no access to a row specified in a change, that change
 // is excluded from the result stream.
 //
@@ -3837,7 +3837,7 @@
 // without re-ordering. See watch.GlobWatcher for a detailed explanation of the
 // behavior.
 // TODO(rogulenko): Currently the only supported watch patterns are
-// "<tableName>/<rowPrefix>*". Consider changing that.
+// "<collectionName>/<rowPrefix>*". Consider changing that.
 //
 // Watching is done by starting a streaming RPC. The RPC takes a ResumeMarker
 // argument that points to a particular place in the database event log. If an
@@ -3846,8 +3846,8 @@
 // only changes since the provided ResumeMarker.
 //
 // The result stream consists of a never-ending sequence of Change messages
-// (until the call fails or is canceled). Each Change contains the Name field
-// in the form "<tableName>/<rowKey>" and the Value field of the StoreChange
+// (until the call fails or is canceled). Each Change contains the Name field in
+// the form "<collectionName>/<rowKey>" and the Value field of the StoreChange
 // type. If the client has no access to a row specified in a change, that change
 // is excluded from the result stream.
 //
@@ -3927,7 +3927,7 @@
 var descDatabaseWatcher = rpc.InterfaceDesc{
 	Name:    "DatabaseWatcher",
 	PkgPath: "v.io/v23/services/syncbase",
-	Doc:     "// DatabaseWatcher allows a client to watch for updates to the database. For\n// each watch request, the client will receive a reliable stream of watch events\n// without re-ordering. See watch.GlobWatcher for a detailed explanation of the\n// behavior.\n// TODO(rogulenko): Currently the only supported watch patterns are\n// \"<tableName>/<rowPrefix>*\". Consider changing that.\n//\n// Watching is done by starting a streaming RPC. The RPC takes a ResumeMarker\n// argument that points to a particular place in the database event log. If an\n// empty ResumeMarker is provided, the WatchStream will begin with a Change\n// batch containing the initial state. Otherwise, the WatchStream will contain\n// only changes since the provided ResumeMarker.\n//\n// The result stream consists of a never-ending sequence of Change messages\n// (until the call fails or is canceled). Each Change contains the Name field\n// in the form \"<tableName>/<rowKey>\" and the Value field of the StoreChange\n// type. If the client has no access to a row specified in a change, that change\n// is excluded from the result stream.\n//\n// Note: A single Watch Change batch may contain changes from more than one\n// batch as originally committed on a remote Syncbase or obtained from conflict\n// resolution. However, changes from a single original batch will always appear\n// in the same Change batch.",
+	Doc:     "// DatabaseWatcher allows a client to watch for updates to the database. For\n// each watch request, the client will receive a reliable stream of watch events\n// without re-ordering. See watch.GlobWatcher for a detailed explanation of the\n// behavior.\n// TODO(rogulenko): Currently the only supported watch patterns are\n// \"<collectionName>/<rowPrefix>*\". Consider changing that.\n//\n// Watching is done by starting a streaming RPC. The RPC takes a ResumeMarker\n// argument that points to a particular place in the database event log. If an\n// empty ResumeMarker is provided, the WatchStream will begin with a Change\n// batch containing the initial state. Otherwise, the WatchStream will contain\n// only changes since the provided ResumeMarker.\n//\n// The result stream consists of a never-ending sequence of Change messages\n// (until the call fails or is canceled). Each Change contains the Name field in\n// the form \"<collectionName>/<rowKey>\" and the Value field of the StoreChange\n// type. If the client has no access to a row specified in a change, that change\n// is excluded from the result stream.\n//\n// Note: A single Watch Change batch may contain changes from more than one\n// batch as originally committed on a remote Syncbase or obtained from conflict\n// resolution. However, changes from a single original batch will always appear\n// in the same Change batch.",
 	Embeds: []rpc.EmbedDesc{
 		{"GlobWatcher", "v.io/v23/services/watch", "// GlobWatcher allows a client to receive updates for changes to objects\n// that match a pattern.  See the package comments for details."},
 	},
@@ -5504,9 +5504,9 @@
 // DatabaseClientMethods is the client interface
 // containing Database methods.
 //
-// Database represents a collection of Tables. Batches, queries, sync, watch,
-// etc. all operate at the Database level.
-// Database.Glob operates over Table names.
+// Database represents a set of Collections. Batches, queries, sync, watch, etc.
+// all operate at the Database level.
+// Database.Glob operates over Collection names.
 // Param schemaVersion is the version number that the client expects the
 // database to be at. To disable schema version checking, pass -1.
 type DatabaseClientMethods interface {
@@ -5560,7 +5560,7 @@
 	// without re-ordering. See watch.GlobWatcher for a detailed explanation of the
 	// behavior.
 	// TODO(rogulenko): Currently the only supported watch patterns are
-	// "<tableName>/<rowPrefix>*". Consider changing that.
+	// "<collectionName>/<rowPrefix>*". Consider changing that.
 	//
 	// Watching is done by starting a streaming RPC. The RPC takes a ResumeMarker
 	// argument that points to a particular place in the database event log. If an
@@ -5569,8 +5569,8 @@
 	// only changes since the provided ResumeMarker.
 	//
 	// The result stream consists of a never-ending sequence of Change messages
-	// (until the call fails or is canceled). Each Change contains the Name field
-	// in the form "<tableName>/<rowKey>" and the Value field of the StoreChange
+	// (until the call fails or is canceled). Each Change contains the Name field in
+	// the form "<collectionName>/<rowKey>" and the Value field of the StoreChange
 	// type. If the client has no access to a row specified in a change, that change
 	// is excluded from the result stream.
 	//
@@ -5610,7 +5610,7 @@
 	// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy
 	// do not exist.
 	Exists(_ *context.T, schemaVersion int32, _ ...rpc.CallOpt) (bool, error)
-	// ListTables returns a list of all Table names.
+	// ListCollections returns a list of all Collection names.
 	// This method exists on Database but not on Service or App because for the
 	// latter we can simply use glob, while for the former glob fails on
 	// BatchDatabase since we encode the batch id in the BatchDatabase object
@@ -5623,7 +5623,7 @@
 	//    results. This is inefficient in general, and broken for us since
 	//    Glob("app/*") does not return batch database names like "a/d##bId".
 	// TODO(sadovsky): Maybe switch to streaming RPC.
-	ListTables(*context.T, ...rpc.CallOpt) ([]string, error)
+	ListCollections(*context.T, ...rpc.CallOpt) ([]string, error)
 	// Exec executes a syncQL query with positional parameters and returns all
 	// results as specified by the query's select/delete statement.
 	// Concurrency semantics are documented in model.go.
@@ -5693,8 +5693,8 @@
 	return
 }
 
-func (c implDatabaseClientStub) ListTables(ctx *context.T, opts ...rpc.CallOpt) (o0 []string, err error) {
-	err = v23.GetClient(ctx).Call(ctx, c.name, "ListTables", nil, []interface{}{&o0}, opts...)
+func (c implDatabaseClientStub) ListCollections(ctx *context.T, opts ...rpc.CallOpt) (o0 []string, err error) {
+	err = v23.GetClient(ctx).Call(ctx, c.name, "ListCollections", nil, []interface{}{&o0}, opts...)
 	return
 }
 
@@ -5803,9 +5803,9 @@
 // DatabaseServerMethods is the interface a server writer
 // implements for Database.
 //
-// Database represents a collection of Tables. Batches, queries, sync, watch,
-// etc. all operate at the Database level.
-// Database.Glob operates over Table names.
+// Database represents a set of Collections. Batches, queries, sync, watch, etc.
+// all operate at the Database level.
+// Database.Glob operates over Collection names.
 // Param schemaVersion is the version number that the client expects the
 // database to be at. To disable schema version checking, pass -1.
 type DatabaseServerMethods interface {
@@ -5859,7 +5859,7 @@
 	// without re-ordering. See watch.GlobWatcher for a detailed explanation of the
 	// behavior.
 	// TODO(rogulenko): Currently the only supported watch patterns are
-	// "<tableName>/<rowPrefix>*". Consider changing that.
+	// "<collectionName>/<rowPrefix>*". Consider changing that.
 	//
 	// Watching is done by starting a streaming RPC. The RPC takes a ResumeMarker
 	// argument that points to a particular place in the database event log. If an
@@ -5868,8 +5868,8 @@
 	// only changes since the provided ResumeMarker.
 	//
 	// The result stream consists of a never-ending sequence of Change messages
-	// (until the call fails or is canceled). Each Change contains the Name field
-	// in the form "<tableName>/<rowKey>" and the Value field of the StoreChange
+	// (until the call fails or is canceled). Each Change contains the Name field in
+	// the form "<collectionName>/<rowKey>" and the Value field of the StoreChange
 	// type. If the client has no access to a row specified in a change, that change
 	// is excluded from the result stream.
 	//
@@ -5909,7 +5909,7 @@
 	// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy
 	// do not exist.
 	Exists(_ *context.T, _ rpc.ServerCall, schemaVersion int32) (bool, error)
-	// ListTables returns a list of all Table names.
+	// ListCollections returns a list of all Collection names.
 	// This method exists on Database but not on Service or App because for the
 	// latter we can simply use glob, while for the former glob fails on
 	// BatchDatabase since we encode the batch id in the BatchDatabase object
@@ -5922,7 +5922,7 @@
 	//    results. This is inefficient in general, and broken for us since
 	//    Glob("app/*") does not return batch database names like "a/d##bId".
 	// TODO(sadovsky): Maybe switch to streaming RPC.
-	ListTables(*context.T, rpc.ServerCall) ([]string, error)
+	ListCollections(*context.T, rpc.ServerCall) ([]string, error)
 	// Exec executes a syncQL query with positional parameters and returns all
 	// results as specified by the query's select/delete statement.
 	// Concurrency semantics are documented in model.go.
@@ -6010,7 +6010,7 @@
 	// without re-ordering. See watch.GlobWatcher for a detailed explanation of the
 	// behavior.
 	// TODO(rogulenko): Currently the only supported watch patterns are
-	// "<tableName>/<rowPrefix>*". Consider changing that.
+	// "<collectionName>/<rowPrefix>*". Consider changing that.
 	//
 	// Watching is done by starting a streaming RPC. The RPC takes a ResumeMarker
 	// argument that points to a particular place in the database event log. If an
@@ -6019,8 +6019,8 @@
 	// only changes since the provided ResumeMarker.
 	//
 	// The result stream consists of a never-ending sequence of Change messages
-	// (until the call fails or is canceled). Each Change contains the Name field
-	// in the form "<tableName>/<rowKey>" and the Value field of the StoreChange
+	// (until the call fails or is canceled). Each Change contains the Name field in
+	// the form "<collectionName>/<rowKey>" and the Value field of the StoreChange
 	// type. If the client has no access to a row specified in a change, that change
 	// is excluded from the result stream.
 	//
@@ -6060,7 +6060,7 @@
 	// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy
 	// do not exist.
 	Exists(_ *context.T, _ rpc.ServerCall, schemaVersion int32) (bool, error)
-	// ListTables returns a list of all Table names.
+	// ListCollections returns a list of all Collection names.
 	// This method exists on Database but not on Service or App because for the
 	// latter we can simply use glob, while for the former glob fails on
 	// BatchDatabase since we encode the batch id in the BatchDatabase object
@@ -6073,7 +6073,7 @@
 	//    results. This is inefficient in general, and broken for us since
 	//    Glob("app/*") does not return batch database names like "a/d##bId".
 	// TODO(sadovsky): Maybe switch to streaming RPC.
-	ListTables(*context.T, rpc.ServerCall) ([]string, error)
+	ListCollections(*context.T, rpc.ServerCall) ([]string, error)
 	// Exec executes a syncQL query with positional parameters and returns all
 	// results as specified by the query's select/delete statement.
 	// Concurrency semantics are documented in model.go.
@@ -6159,8 +6159,8 @@
 	return s.impl.Exists(ctx, call, i0)
 }
 
-func (s implDatabaseServerStub) ListTables(ctx *context.T, call rpc.ServerCall) ([]string, error) {
-	return s.impl.ListTables(ctx, call)
+func (s implDatabaseServerStub) ListCollections(ctx *context.T, call rpc.ServerCall) ([]string, error) {
+	return s.impl.ListCollections(ctx, call)
 }
 
 func (s implDatabaseServerStub) Exec(ctx *context.T, call *DatabaseExecServerCallStub, i0 int32, i1 string, i2 []*vom.RawBytes) error {
@@ -6202,10 +6202,10 @@
 var descDatabase = rpc.InterfaceDesc{
 	Name:    "Database",
 	PkgPath: "v.io/v23/services/syncbase",
-	Doc:     "// Database represents a collection of Tables. Batches, queries, sync, watch,\n// etc. all operate at the Database level.\n// Database.Glob operates over Table names.\n// Param schemaVersion is the version number that the client expects the\n// database to be at. To disable schema version checking, pass -1.",
+	Doc:     "// Database represents a set of Collections. Batches, queries, sync, watch, etc.\n// all operate at the Database level.\n// Database.Glob operates over Collection names.\n// Param schemaVersion is the version number that the client expects the\n// database to be at. To disable schema version checking, pass -1.",
 	Embeds: []rpc.EmbedDesc{
 		{"Object", "v.io/v23/services/permissions", "// Object provides access control for Vanadium objects.\n//\n// Vanadium services implementing dynamic access control would typically embed\n// this interface and tag additional methods defined by the service with one of\n// Admin, Read, Write, Resolve etc. For example, the VDL definition of the\n// object would be:\n//\n//   package mypackage\n//\n//   import \"v.io/v23/security/access\"\n//   import \"v.io/v23/services/permissions\"\n//\n//   type MyObject interface {\n//     permissions.Object\n//     MyRead() (string, error) {access.Read}\n//     MyWrite(string) error    {access.Write}\n//   }\n//\n// If the set of pre-defined tags is insufficient, services may define their\n// own tag type and annotate all methods with this new type.\n//\n// Instead of embedding this Object interface, define SetPermissions and\n// GetPermissions in their own interface. Authorization policies will typically\n// respect annotations of a single type. For example, the VDL definition of an\n// object would be:\n//\n//  package mypackage\n//\n//  import \"v.io/v23/security/access\"\n//\n//  type MyTag string\n//\n//  const (\n//    Blue = MyTag(\"Blue\")\n//    Red  = MyTag(\"Red\")\n//  )\n//\n//  type MyObject interface {\n//    MyMethod() (string, error) {Blue}\n//\n//    // Allow clients to change access via the access.Object interface:\n//    SetPermissions(perms access.Permissions, version string) error         {Red}\n//    GetPermissions() (perms access.Permissions, version string, err error) {Blue}\n//  }"},
-		{"DatabaseWatcher", "v.io/v23/services/syncbase", "// DatabaseWatcher allows a client to watch for updates to the database. For\n// each watch request, the client will receive a reliable stream of watch events\n// without re-ordering. See watch.GlobWatcher for a detailed explanation of the\n// behavior.\n// TODO(rogulenko): Currently the only supported watch patterns are\n// \"<tableName>/<rowPrefix>*\". Consider changing that.\n//\n// Watching is done by starting a streaming RPC. The RPC takes a ResumeMarker\n// argument that points to a particular place in the database event log. If an\n// empty ResumeMarker is provided, the WatchStream will begin with a Change\n// batch containing the initial state. Otherwise, the WatchStream will contain\n// only changes since the provided ResumeMarker.\n//\n// The result stream consists of a never-ending sequence of Change messages\n// (until the call fails or is canceled). Each Change contains the Name field\n// in the form \"<tableName>/<rowKey>\" and the Value field of the StoreChange\n// type. If the client has no access to a row specified in a change, that change\n// is excluded from the result stream.\n//\n// Note: A single Watch Change batch may contain changes from more than one\n// batch as originally committed on a remote Syncbase or obtained from conflict\n// resolution. However, changes from a single original batch will always appear\n// in the same Change batch."},
+		{"DatabaseWatcher", "v.io/v23/services/syncbase", "// DatabaseWatcher allows a client to watch for updates to the database. For\n// each watch request, the client will receive a reliable stream of watch events\n// without re-ordering. See watch.GlobWatcher for a detailed explanation of the\n// behavior.\n// TODO(rogulenko): Currently the only supported watch patterns are\n// \"<collectionName>/<rowPrefix>*\". Consider changing that.\n//\n// Watching is done by starting a streaming RPC. The RPC takes a ResumeMarker\n// argument that points to a particular place in the database event log. If an\n// empty ResumeMarker is provided, the WatchStream will begin with a Change\n// batch containing the initial state. Otherwise, the WatchStream will contain\n// only changes since the provided ResumeMarker.\n//\n// The result stream consists of a never-ending sequence of Change messages\n// (until the call fails or is canceled). Each Change contains the Name field in\n// the form \"<collectionName>/<rowKey>\" and the Value field of the StoreChange\n// type. If the client has no access to a row specified in a change, that change\n// is excluded from the result stream.\n//\n// Note: A single Watch Change batch may contain changes from more than one\n// batch as originally committed on a remote Syncbase or obtained from conflict\n// resolution. However, changes from a single original batch will always appear\n// in the same Change batch."},
 		{"SyncgroupManager", "v.io/v23/services/syncbase", "// SyncgroupManager is the interface for syncgroup operations.\n// TODO(hpucha): Add blessings to create/join and add a refresh method."},
 		{"BlobManager", "v.io/v23/services/syncbase", "// BlobManager is the interface for blob operations.\n//\n// Description of API for resumable blob creation (append-only):\n// - Up until commit, a BlobRef may be used with PutBlob, GetBlobSize,\n//   DeleteBlob, and CommitBlob. Blob creation may be resumed by obtaining the\n//   current blob size via GetBlobSize and appending to the blob via PutBlob.\n// - After commit, a blob is immutable, at which point PutBlob and CommitBlob\n//   may no longer be used.\n// - All other methods (GetBlob, FetchBlob, PinBlob, etc.) may only be used\n//   after commit."},
 		{"SchemaManager", "v.io/v23/services/syncbase", "// SchemaManager implements the API for managing schema metadata attached\n// to a Database."},
@@ -6241,8 +6241,8 @@
 			Tags: []*vdl.Value{vdl.ValueOf(access.Tag("Resolve"))},
 		},
 		{
-			Name: "ListTables",
-			Doc:  "// ListTables returns a list of all Table names.\n// This method exists on Database but not on Service or App because for the\n// latter we can simply use glob, while for the former glob fails on\n// BatchDatabase since we encode the batch id in the BatchDatabase object\n// name. More specifically, the glob client library appears to have two odd\n// behaviors:\n// 1) It checks Resolve access on every component along the path (by doing a\n//    Dispatcher.Lookup), whereas this doesn't happen for other RPCs.\n// 2) It does a Glob(<prefix>/*) for every prefix path, and only proceeds to\n//    the next path component if that component appeared in its parent's Glob\n//    results. This is inefficient in general, and broken for us since\n//    Glob(\"app/*\") does not return batch database names like \"a/d##bId\".\n// TODO(sadovsky): Maybe switch to streaming RPC.",
+			Name: "ListCollections",
+			Doc:  "// ListCollections returns a list of all Collection names.\n// This method exists on Database but not on Service or App because for the\n// latter we can simply use glob, while for the former glob fails on\n// BatchDatabase since we encode the batch id in the BatchDatabase object\n// name. More specifically, the glob client library appears to have two odd\n// behaviors:\n// 1) It checks Resolve access on every component along the path (by doing a\n//    Dispatcher.Lookup), whereas this doesn't happen for other RPCs.\n// 2) It does a Glob(<prefix>/*) for every prefix path, and only proceeds to\n//    the next path component if that component appeared in its parent's Glob\n//    results. This is inefficient in general, and broken for us since\n//    Glob(\"app/*\") does not return batch database names like \"a/d##bId\".\n// TODO(sadovsky): Maybe switch to streaming RPC.",
 			OutArgs: []rpc.ArgDesc{
 				{"", ``}, // []string
 			},
@@ -6342,27 +6342,27 @@
 	return s.s.Send(item)
 }
 
-// TableClientMethods is the client interface
-// containing Table methods.
+// CollectionClientMethods is the client interface
+// containing Collection methods.
 //
-// Table represents a collection of Rows.
-// Table.Glob operates over the primary keys of Rows in the Table.
+// Collection represents a collection of Rows.
+// Collection.Glob operates over the primary keys of Rows in the Collection.
 // SchemaVersion is the version number that the client expects the database
 // to be at. To disable schema version checking, pass -1.
-type TableClientMethods interface {
-	// Create creates this Table.
+type CollectionClientMethods interface {
+	// Create creates this Collection.
 	// If perms is nil, we inherit (copy) the Database perms.
 	Create(_ *context.T, schemaVersion int32, perms access.Permissions, _ ...rpc.CallOpt) error
-	// Destroy destroys this Table.
+	// Destroy destroys this Collection.
 	Destroy(_ *context.T, schemaVersion int32, _ ...rpc.CallOpt) error
-	// Exists returns true only if this Table exists. Insufficient permissions
-	// cause Exists to return false instead of an error.
+	// Exists returns true only if this Collection exists. Insufficient
+	// permissions cause Exists to return false instead of an error.
 	// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy
 	// do not exist.
 	Exists(_ *context.T, schemaVersion int32, _ ...rpc.CallOpt) (bool, error)
-	// GetPermissions returns the current Permissions for the Table.
+	// GetPermissions returns the current Permissions for the Collection.
 	GetPermissions(_ *context.T, schemaVersion int32, _ ...rpc.CallOpt) (access.Permissions, error)
-	// SetPermissions replaces the current Permissions for the Table.
+	// SetPermissions replaces the current Permissions for the Collection.
 	SetPermissions(_ *context.T, schemaVersion int32, perms access.Permissions, _ ...rpc.CallOpt) error
 	// DeleteRange deletes all rows in the given half-open range [start, limit).
 	// If limit is "", all rows with keys >= start are included.
@@ -6372,12 +6372,12 @@
 	// Scan returns all rows in the given half-open range [start, limit). If limit
 	// is "", all rows with keys >= start are included. Concurrency semantics are
 	// documented in model.go.
-	Scan(_ *context.T, schemaVersion int32, start []byte, limit []byte, _ ...rpc.CallOpt) (TableScanClientCall, error)
-	// GetPrefixPermissions returns an array of (prefix, perms) pairs. The array is
-	// sorted from longest prefix to shortest, so element zero is the one that
+	Scan(_ *context.T, schemaVersion int32, start []byte, limit []byte, _ ...rpc.CallOpt) (CollectionScanClientCall, error)
+	// GetPrefixPermissions returns an array of (prefix, perms) pairs. The array
+	// is sorted from longest prefix to shortest, so element zero is the one that
 	// applies to the row with the given key. The last element is always the
-	// prefix "" which represents the table's permissions -- the array will always
-	// have at least one element.
+	// prefix "" which represents the collection's permissions -- the array will
+	// always have at least one element.
 	GetPrefixPermissions(_ *context.T, schemaVersion int32, key string, _ ...rpc.CallOpt) ([]PrefixPermissions, error)
 	// SetPrefixPermissions sets the permissions for all current and future rows with
 	// the given prefix. If the prefix overlaps with an existing prefix, the
@@ -6393,78 +6393,78 @@
 	DeletePrefixPermissions(_ *context.T, schemaVersion int32, prefix string, _ ...rpc.CallOpt) error
 }
 
-// TableClientStub adds universal methods to TableClientMethods.
-type TableClientStub interface {
-	TableClientMethods
+// CollectionClientStub adds universal methods to CollectionClientMethods.
+type CollectionClientStub interface {
+	CollectionClientMethods
 	rpc.UniversalServiceMethods
 }
 
-// TableClient returns a client stub for Table.
-func TableClient(name string) TableClientStub {
-	return implTableClientStub{name}
+// CollectionClient returns a client stub for Collection.
+func CollectionClient(name string) CollectionClientStub {
+	return implCollectionClientStub{name}
 }
 
-type implTableClientStub struct {
+type implCollectionClientStub struct {
 	name string
 }
 
-func (c implTableClientStub) Create(ctx *context.T, i0 int32, i1 access.Permissions, opts ...rpc.CallOpt) (err error) {
+func (c implCollectionClientStub) Create(ctx *context.T, i0 int32, i1 access.Permissions, opts ...rpc.CallOpt) (err error) {
 	err = v23.GetClient(ctx).Call(ctx, c.name, "Create", []interface{}{i0, i1}, nil, opts...)
 	return
 }
 
-func (c implTableClientStub) Destroy(ctx *context.T, i0 int32, opts ...rpc.CallOpt) (err error) {
+func (c implCollectionClientStub) Destroy(ctx *context.T, i0 int32, opts ...rpc.CallOpt) (err error) {
 	err = v23.GetClient(ctx).Call(ctx, c.name, "Destroy", []interface{}{i0}, nil, opts...)
 	return
 }
 
-func (c implTableClientStub) Exists(ctx *context.T, i0 int32, opts ...rpc.CallOpt) (o0 bool, err error) {
+func (c implCollectionClientStub) Exists(ctx *context.T, i0 int32, opts ...rpc.CallOpt) (o0 bool, err error) {
 	err = v23.GetClient(ctx).Call(ctx, c.name, "Exists", []interface{}{i0}, []interface{}{&o0}, opts...)
 	return
 }
 
-func (c implTableClientStub) GetPermissions(ctx *context.T, i0 int32, opts ...rpc.CallOpt) (o0 access.Permissions, err error) {
+func (c implCollectionClientStub) GetPermissions(ctx *context.T, i0 int32, opts ...rpc.CallOpt) (o0 access.Permissions, err error) {
 	err = v23.GetClient(ctx).Call(ctx, c.name, "GetPermissions", []interface{}{i0}, []interface{}{&o0}, opts...)
 	return
 }
 
-func (c implTableClientStub) SetPermissions(ctx *context.T, i0 int32, i1 access.Permissions, opts ...rpc.CallOpt) (err error) {
+func (c implCollectionClientStub) SetPermissions(ctx *context.T, i0 int32, i1 access.Permissions, opts ...rpc.CallOpt) (err error) {
 	err = v23.GetClient(ctx).Call(ctx, c.name, "SetPermissions", []interface{}{i0, i1}, nil, opts...)
 	return
 }
 
-func (c implTableClientStub) DeleteRange(ctx *context.T, i0 int32, i1 []byte, i2 []byte, opts ...rpc.CallOpt) (err error) {
+func (c implCollectionClientStub) DeleteRange(ctx *context.T, i0 int32, i1 []byte, i2 []byte, opts ...rpc.CallOpt) (err error) {
 	err = v23.GetClient(ctx).Call(ctx, c.name, "DeleteRange", []interface{}{i0, i1, i2}, nil, opts...)
 	return
 }
 
-func (c implTableClientStub) Scan(ctx *context.T, i0 int32, i1 []byte, i2 []byte, opts ...rpc.CallOpt) (ocall TableScanClientCall, err error) {
+func (c implCollectionClientStub) Scan(ctx *context.T, i0 int32, i1 []byte, i2 []byte, opts ...rpc.CallOpt) (ocall CollectionScanClientCall, err error) {
 	var call rpc.ClientCall
 	if call, err = v23.GetClient(ctx).StartCall(ctx, c.name, "Scan", []interface{}{i0, i1, i2}, opts...); err != nil {
 		return
 	}
-	ocall = &implTableScanClientCall{ClientCall: call}
+	ocall = &implCollectionScanClientCall{ClientCall: call}
 	return
 }
 
-func (c implTableClientStub) GetPrefixPermissions(ctx *context.T, i0 int32, i1 string, opts ...rpc.CallOpt) (o0 []PrefixPermissions, err error) {
+func (c implCollectionClientStub) GetPrefixPermissions(ctx *context.T, i0 int32, i1 string, opts ...rpc.CallOpt) (o0 []PrefixPermissions, err error) {
 	err = v23.GetClient(ctx).Call(ctx, c.name, "GetPrefixPermissions", []interface{}{i0, i1}, []interface{}{&o0}, opts...)
 	return
 }
 
-func (c implTableClientStub) SetPrefixPermissions(ctx *context.T, i0 int32, i1 string, i2 access.Permissions, opts ...rpc.CallOpt) (err error) {
+func (c implCollectionClientStub) SetPrefixPermissions(ctx *context.T, i0 int32, i1 string, i2 access.Permissions, opts ...rpc.CallOpt) (err error) {
 	err = v23.GetClient(ctx).Call(ctx, c.name, "SetPrefixPermissions", []interface{}{i0, i1, i2}, nil, opts...)
 	return
 }
 
-func (c implTableClientStub) DeletePrefixPermissions(ctx *context.T, i0 int32, i1 string, opts ...rpc.CallOpt) (err error) {
+func (c implCollectionClientStub) DeletePrefixPermissions(ctx *context.T, i0 int32, i1 string, opts ...rpc.CallOpt) (err error) {
 	err = v23.GetClient(ctx).Call(ctx, c.name, "DeletePrefixPermissions", []interface{}{i0, i1}, nil, opts...)
 	return
 }
 
-// TableScanClientStream is the client stream for Table.Scan.
-type TableScanClientStream interface {
-	// RecvStream returns the receiver side of the Table.Scan client stream.
+// CollectionScanClientStream is the client stream for Collection.Scan.
+type CollectionScanClientStream interface {
+	// RecvStream returns the receiver side of the Collection.Scan client stream.
 	RecvStream() interface {
 		// Advance stages an item so that it may be retrieved via Value.  Returns
 		// true iff there is an item to retrieve.  Advance must be called before
@@ -6478,9 +6478,9 @@
 	}
 }
 
-// TableScanClientCall represents the call returned from Table.Scan.
-type TableScanClientCall interface {
-	TableScanClientStream
+// CollectionScanClientCall represents the call returned from Collection.Scan.
+type CollectionScanClientCall interface {
+	CollectionScanClientStream
 	// Finish blocks until the server is done, and returns the positional return
 	// values for call.
 	//
@@ -6494,64 +6494,64 @@
 	Finish() error
 }
 
-type implTableScanClientCall struct {
+type implCollectionScanClientCall struct {
 	rpc.ClientCall
 	valRecv KeyValue
 	errRecv error
 }
 
-func (c *implTableScanClientCall) RecvStream() interface {
+func (c *implCollectionScanClientCall) RecvStream() interface {
 	Advance() bool
 	Value() KeyValue
 	Err() error
 } {
-	return implTableScanClientCallRecv{c}
+	return implCollectionScanClientCallRecv{c}
 }
 
-type implTableScanClientCallRecv struct {
-	c *implTableScanClientCall
+type implCollectionScanClientCallRecv struct {
+	c *implCollectionScanClientCall
 }
 
-func (c implTableScanClientCallRecv) Advance() bool {
+func (c implCollectionScanClientCallRecv) Advance() bool {
 	c.c.valRecv = KeyValue{}
 	c.c.errRecv = c.c.Recv(&c.c.valRecv)
 	return c.c.errRecv == nil
 }
-func (c implTableScanClientCallRecv) Value() KeyValue {
+func (c implCollectionScanClientCallRecv) Value() KeyValue {
 	return c.c.valRecv
 }
-func (c implTableScanClientCallRecv) Err() error {
+func (c implCollectionScanClientCallRecv) Err() error {
 	if c.c.errRecv == io.EOF {
 		return nil
 	}
 	return c.c.errRecv
 }
-func (c *implTableScanClientCall) Finish() (err error) {
+func (c *implCollectionScanClientCall) Finish() (err error) {
 	err = c.ClientCall.Finish()
 	return
 }
 
-// TableServerMethods is the interface a server writer
-// implements for Table.
+// CollectionServerMethods is the interface a server writer
+// implements for Collection.
 //
-// Table represents a collection of Rows.
-// Table.Glob operates over the primary keys of Rows in the Table.
+// Collection represents a collection of Rows.
+// Collection.Glob operates over the primary keys of Rows in the Collection.
 // SchemaVersion is the version number that the client expects the database
 // to be at. To disable schema version checking, pass -1.
-type TableServerMethods interface {
-	// Create creates this Table.
+type CollectionServerMethods interface {
+	// Create creates this Collection.
 	// If perms is nil, we inherit (copy) the Database perms.
 	Create(_ *context.T, _ rpc.ServerCall, schemaVersion int32, perms access.Permissions) error
-	// Destroy destroys this Table.
+	// Destroy destroys this Collection.
 	Destroy(_ *context.T, _ rpc.ServerCall, schemaVersion int32) error
-	// Exists returns true only if this Table exists. Insufficient permissions
-	// cause Exists to return false instead of an error.
+	// Exists returns true only if this Collection exists. Insufficient
+	// permissions cause Exists to return false instead of an error.
 	// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy
 	// do not exist.
 	Exists(_ *context.T, _ rpc.ServerCall, schemaVersion int32) (bool, error)
-	// GetPermissions returns the current Permissions for the Table.
+	// GetPermissions returns the current Permissions for the Collection.
 	GetPermissions(_ *context.T, _ rpc.ServerCall, schemaVersion int32) (access.Permissions, error)
-	// SetPermissions replaces the current Permissions for the Table.
+	// SetPermissions replaces the current Permissions for the Collection.
 	SetPermissions(_ *context.T, _ rpc.ServerCall, schemaVersion int32, perms access.Permissions) error
 	// DeleteRange deletes all rows in the given half-open range [start, limit).
 	// If limit is "", all rows with keys >= start are included.
@@ -6561,12 +6561,12 @@
 	// Scan returns all rows in the given half-open range [start, limit). If limit
 	// is "", all rows with keys >= start are included. Concurrency semantics are
 	// documented in model.go.
-	Scan(_ *context.T, _ TableScanServerCall, schemaVersion int32, start []byte, limit []byte) error
-	// GetPrefixPermissions returns an array of (prefix, perms) pairs. The array is
-	// sorted from longest prefix to shortest, so element zero is the one that
+	Scan(_ *context.T, _ CollectionScanServerCall, schemaVersion int32, start []byte, limit []byte) error
+	// GetPrefixPermissions returns an array of (prefix, perms) pairs. The array
+	// is sorted from longest prefix to shortest, so element zero is the one that
 	// applies to the row with the given key. The last element is always the
-	// prefix "" which represents the table's permissions -- the array will always
-	// have at least one element.
+	// prefix "" which represents the collection's permissions -- the array will
+	// always have at least one element.
 	GetPrefixPermissions(_ *context.T, _ rpc.ServerCall, schemaVersion int32, key string) ([]PrefixPermissions, error)
 	// SetPrefixPermissions sets the permissions for all current and future rows with
 	// the given prefix. If the prefix overlaps with an existing prefix, the
@@ -6582,24 +6582,24 @@
 	DeletePrefixPermissions(_ *context.T, _ rpc.ServerCall, schemaVersion int32, prefix string) error
 }
 
-// TableServerStubMethods is the server interface containing
-// Table methods, as expected by rpc.Server.
-// The only difference between this interface and TableServerMethods
+// CollectionServerStubMethods is the server interface containing
+// Collection methods, as expected by rpc.Server.
+// The only difference between this interface and CollectionServerMethods
 // is the streaming methods.
-type TableServerStubMethods interface {
-	// Create creates this Table.
+type CollectionServerStubMethods interface {
+	// Create creates this Collection.
 	// If perms is nil, we inherit (copy) the Database perms.
 	Create(_ *context.T, _ rpc.ServerCall, schemaVersion int32, perms access.Permissions) error
-	// Destroy destroys this Table.
+	// Destroy destroys this Collection.
 	Destroy(_ *context.T, _ rpc.ServerCall, schemaVersion int32) error
-	// Exists returns true only if this Table exists. Insufficient permissions
-	// cause Exists to return false instead of an error.
+	// Exists returns true only if this Collection exists. Insufficient
+	// permissions cause Exists to return false instead of an error.
 	// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy
 	// do not exist.
 	Exists(_ *context.T, _ rpc.ServerCall, schemaVersion int32) (bool, error)
-	// GetPermissions returns the current Permissions for the Table.
+	// GetPermissions returns the current Permissions for the Collection.
 	GetPermissions(_ *context.T, _ rpc.ServerCall, schemaVersion int32) (access.Permissions, error)
-	// SetPermissions replaces the current Permissions for the Table.
+	// SetPermissions replaces the current Permissions for the Collection.
 	SetPermissions(_ *context.T, _ rpc.ServerCall, schemaVersion int32, perms access.Permissions) error
 	// DeleteRange deletes all rows in the given half-open range [start, limit).
 	// If limit is "", all rows with keys >= start are included.
@@ -6609,12 +6609,12 @@
 	// Scan returns all rows in the given half-open range [start, limit). If limit
 	// is "", all rows with keys >= start are included. Concurrency semantics are
 	// documented in model.go.
-	Scan(_ *context.T, _ *TableScanServerCallStub, schemaVersion int32, start []byte, limit []byte) error
-	// GetPrefixPermissions returns an array of (prefix, perms) pairs. The array is
-	// sorted from longest prefix to shortest, so element zero is the one that
+	Scan(_ *context.T, _ *CollectionScanServerCallStub, schemaVersion int32, start []byte, limit []byte) error
+	// GetPrefixPermissions returns an array of (prefix, perms) pairs. The array
+	// is sorted from longest prefix to shortest, so element zero is the one that
 	// applies to the row with the given key. The last element is always the
-	// prefix "" which represents the table's permissions -- the array will always
-	// have at least one element.
+	// prefix "" which represents the collection's permissions -- the array will
+	// always have at least one element.
 	GetPrefixPermissions(_ *context.T, _ rpc.ServerCall, schemaVersion int32, key string) ([]PrefixPermissions, error)
 	// SetPrefixPermissions sets the permissions for all current and future rows with
 	// the given prefix. If the prefix overlaps with an existing prefix, the
@@ -6630,18 +6630,18 @@
 	DeletePrefixPermissions(_ *context.T, _ rpc.ServerCall, schemaVersion int32, prefix string) error
 }
 
-// TableServerStub adds universal methods to TableServerStubMethods.
-type TableServerStub interface {
-	TableServerStubMethods
-	// Describe the Table interfaces.
+// CollectionServerStub adds universal methods to CollectionServerStubMethods.
+type CollectionServerStub interface {
+	CollectionServerStubMethods
+	// Describe the Collection interfaces.
 	Describe__() []rpc.InterfaceDesc
 }
 
-// TableServer returns a server stub for Table.
-// It converts an implementation of TableServerMethods into
+// CollectionServer returns a server stub for Collection.
+// It converts an implementation of CollectionServerMethods into
 // an object that may be used by rpc.Server.
-func TableServer(impl TableServerMethods) TableServerStub {
-	stub := implTableServerStub{
+func CollectionServer(impl CollectionServerMethods) CollectionServerStub {
+	stub := implCollectionServerStub{
 		impl: impl,
 	}
 	// Initialize GlobState; always check the stub itself first, to handle the
@@ -6654,71 +6654,71 @@
 	return stub
 }
 
-type implTableServerStub struct {
-	impl TableServerMethods
+type implCollectionServerStub struct {
+	impl CollectionServerMethods
 	gs   *rpc.GlobState
 }
 
-func (s implTableServerStub) Create(ctx *context.T, call rpc.ServerCall, i0 int32, i1 access.Permissions) error {
+func (s implCollectionServerStub) Create(ctx *context.T, call rpc.ServerCall, i0 int32, i1 access.Permissions) error {
 	return s.impl.Create(ctx, call, i0, i1)
 }
 
-func (s implTableServerStub) Destroy(ctx *context.T, call rpc.ServerCall, i0 int32) error {
+func (s implCollectionServerStub) Destroy(ctx *context.T, call rpc.ServerCall, i0 int32) error {
 	return s.impl.Destroy(ctx, call, i0)
 }
 
-func (s implTableServerStub) Exists(ctx *context.T, call rpc.ServerCall, i0 int32) (bool, error) {
+func (s implCollectionServerStub) Exists(ctx *context.T, call rpc.ServerCall, i0 int32) (bool, error) {
 	return s.impl.Exists(ctx, call, i0)
 }
 
-func (s implTableServerStub) GetPermissions(ctx *context.T, call rpc.ServerCall, i0 int32) (access.Permissions, error) {
+func (s implCollectionServerStub) GetPermissions(ctx *context.T, call rpc.ServerCall, i0 int32) (access.Permissions, error) {
 	return s.impl.GetPermissions(ctx, call, i0)
 }
 
-func (s implTableServerStub) SetPermissions(ctx *context.T, call rpc.ServerCall, i0 int32, i1 access.Permissions) error {
+func (s implCollectionServerStub) SetPermissions(ctx *context.T, call rpc.ServerCall, i0 int32, i1 access.Permissions) error {
 	return s.impl.SetPermissions(ctx, call, i0, i1)
 }
 
-func (s implTableServerStub) DeleteRange(ctx *context.T, call rpc.ServerCall, i0 int32, i1 []byte, i2 []byte) error {
+func (s implCollectionServerStub) DeleteRange(ctx *context.T, call rpc.ServerCall, i0 int32, i1 []byte, i2 []byte) error {
 	return s.impl.DeleteRange(ctx, call, i0, i1, i2)
 }
 
-func (s implTableServerStub) Scan(ctx *context.T, call *TableScanServerCallStub, i0 int32, i1 []byte, i2 []byte) error {
+func (s implCollectionServerStub) Scan(ctx *context.T, call *CollectionScanServerCallStub, i0 int32, i1 []byte, i2 []byte) error {
 	return s.impl.Scan(ctx, call, i0, i1, i2)
 }
 
-func (s implTableServerStub) GetPrefixPermissions(ctx *context.T, call rpc.ServerCall, i0 int32, i1 string) ([]PrefixPermissions, error) {
+func (s implCollectionServerStub) GetPrefixPermissions(ctx *context.T, call rpc.ServerCall, i0 int32, i1 string) ([]PrefixPermissions, error) {
 	return s.impl.GetPrefixPermissions(ctx, call, i0, i1)
 }
 
-func (s implTableServerStub) SetPrefixPermissions(ctx *context.T, call rpc.ServerCall, i0 int32, i1 string, i2 access.Permissions) error {
+func (s implCollectionServerStub) SetPrefixPermissions(ctx *context.T, call rpc.ServerCall, i0 int32, i1 string, i2 access.Permissions) error {
 	return s.impl.SetPrefixPermissions(ctx, call, i0, i1, i2)
 }
 
-func (s implTableServerStub) DeletePrefixPermissions(ctx *context.T, call rpc.ServerCall, i0 int32, i1 string) error {
+func (s implCollectionServerStub) DeletePrefixPermissions(ctx *context.T, call rpc.ServerCall, i0 int32, i1 string) error {
 	return s.impl.DeletePrefixPermissions(ctx, call, i0, i1)
 }
 
-func (s implTableServerStub) Globber() *rpc.GlobState {
+func (s implCollectionServerStub) Globber() *rpc.GlobState {
 	return s.gs
 }
 
-func (s implTableServerStub) Describe__() []rpc.InterfaceDesc {
-	return []rpc.InterfaceDesc{TableDesc}
+func (s implCollectionServerStub) Describe__() []rpc.InterfaceDesc {
+	return []rpc.InterfaceDesc{CollectionDesc}
 }
 
-// TableDesc describes the Table interface.
-var TableDesc rpc.InterfaceDesc = descTable
+// CollectionDesc describes the Collection interface.
+var CollectionDesc rpc.InterfaceDesc = descCollection
 
-// descTable hides the desc to keep godoc clean.
-var descTable = rpc.InterfaceDesc{
-	Name:    "Table",
+// descCollection hides the desc to keep godoc clean.
+var descCollection = rpc.InterfaceDesc{
+	Name:    "Collection",
 	PkgPath: "v.io/v23/services/syncbase",
-	Doc:     "// Table represents a collection of Rows.\n// Table.Glob operates over the primary keys of Rows in the Table.\n// SchemaVersion is the version number that the client expects the database\n// to be at. To disable schema version checking, pass -1.",
+	Doc:     "// Collection represents a collection of Rows.\n// Collection.Glob operates over the primary keys of Rows in the Collection.\n// SchemaVersion is the version number that the client expects the database\n// to be at. To disable schema version checking, pass -1.",
 	Methods: []rpc.MethodDesc{
 		{
 			Name: "Create",
-			Doc:  "// Create creates this Table.\n// If perms is nil, we inherit (copy) the Database perms.",
+			Doc:  "// Create creates this Collection.\n// If perms is nil, we inherit (copy) the Database perms.",
 			InArgs: []rpc.ArgDesc{
 				{"schemaVersion", ``}, // int32
 				{"perms", ``},         // access.Permissions
@@ -6727,7 +6727,7 @@
 		},
 		{
 			Name: "Destroy",
-			Doc:  "// Destroy destroys this Table.",
+			Doc:  "// Destroy destroys this Collection.",
 			InArgs: []rpc.ArgDesc{
 				{"schemaVersion", ``}, // int32
 			},
@@ -6735,7 +6735,7 @@
 		},
 		{
 			Name: "Exists",
-			Doc:  "// Exists returns true only if this Table exists. Insufficient permissions\n// cause Exists to return false instead of an error.\n// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy\n// do not exist.",
+			Doc:  "// Exists returns true only if this Collection exists. Insufficient\n// permissions cause Exists to return false instead of an error.\n// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy\n// do not exist.",
 			InArgs: []rpc.ArgDesc{
 				{"schemaVersion", ``}, // int32
 			},
@@ -6746,7 +6746,7 @@
 		},
 		{
 			Name: "GetPermissions",
-			Doc:  "// GetPermissions returns the current Permissions for the Table.",
+			Doc:  "// GetPermissions returns the current Permissions for the Collection.",
 			InArgs: []rpc.ArgDesc{
 				{"schemaVersion", ``}, // int32
 			},
@@ -6757,7 +6757,7 @@
 		},
 		{
 			Name: "SetPermissions",
-			Doc:  "// SetPermissions replaces the current Permissions for the Table.",
+			Doc:  "// SetPermissions replaces the current Permissions for the Collection.",
 			InArgs: []rpc.ArgDesc{
 				{"schemaVersion", ``}, // int32
 				{"perms", ``},         // access.Permissions
@@ -6786,7 +6786,7 @@
 		},
 		{
 			Name: "GetPrefixPermissions",
-			Doc:  "// GetPrefixPermissions returns an array of (prefix, perms) pairs. The array is\n// sorted from longest prefix to shortest, so element zero is the one that\n// applies to the row with the given key. The last element is always the\n// prefix \"\" which represents the table's permissions -- the array will always\n// have at least one element.",
+			Doc:  "// GetPrefixPermissions returns an array of (prefix, perms) pairs. The array\n// is sorted from longest prefix to shortest, so element zero is the one that\n// applies to the row with the given key. The last element is always the\n// prefix \"\" which represents the collection's permissions -- the array will\n// always have at least one element.",
 			InArgs: []rpc.ArgDesc{
 				{"schemaVersion", ``}, // int32
 				{"key", ``},           // string
@@ -6818,9 +6818,9 @@
 	},
 }
 
-// TableScanServerStream is the server stream for Table.Scan.
-type TableScanServerStream interface {
-	// SendStream returns the send side of the Table.Scan server stream.
+// CollectionScanServerStream is the server stream for Collection.Scan.
+type CollectionScanServerStream interface {
+	// SendStream returns the send side of the Collection.Scan server stream.
 	SendStream() interface {
 		// Send places the item onto the output stream.  Returns errors encountered
 		// while sending.  Blocks if there is no buffer space; will unblock when
@@ -6829,44 +6829,44 @@
 	}
 }
 
-// TableScanServerCall represents the context passed to Table.Scan.
-type TableScanServerCall interface {
+// CollectionScanServerCall represents the context passed to Collection.Scan.
+type CollectionScanServerCall interface {
 	rpc.ServerCall
-	TableScanServerStream
+	CollectionScanServerStream
 }
 
-// TableScanServerCallStub is a wrapper that converts rpc.StreamServerCall into
-// a typesafe stub that implements TableScanServerCall.
-type TableScanServerCallStub struct {
+// CollectionScanServerCallStub is a wrapper that converts rpc.StreamServerCall into
+// a typesafe stub that implements CollectionScanServerCall.
+type CollectionScanServerCallStub struct {
 	rpc.StreamServerCall
 }
 
-// Init initializes TableScanServerCallStub from rpc.StreamServerCall.
-func (s *TableScanServerCallStub) Init(call rpc.StreamServerCall) {
+// Init initializes CollectionScanServerCallStub from rpc.StreamServerCall.
+func (s *CollectionScanServerCallStub) Init(call rpc.StreamServerCall) {
 	s.StreamServerCall = call
 }
 
-// SendStream returns the send side of the Table.Scan server stream.
-func (s *TableScanServerCallStub) SendStream() interface {
+// SendStream returns the send side of the Collection.Scan server stream.
+func (s *CollectionScanServerCallStub) SendStream() interface {
 	Send(item KeyValue) error
 } {
-	return implTableScanServerCallSend{s}
+	return implCollectionScanServerCallSend{s}
 }
 
-type implTableScanServerCallSend struct {
-	s *TableScanServerCallStub
+type implCollectionScanServerCallSend struct {
+	s *CollectionScanServerCallStub
 }
 
-func (s implTableScanServerCallSend) Send(item KeyValue) error {
+func (s implCollectionScanServerCallSend) Send(item KeyValue) error {
 	return s.s.Send(item)
 }
 
 // RowClientMethods is the client interface
 // containing Row methods.
 //
-// Row represents a single row in a Table.
+// Row represents a single row in a Collection.
 // All access checks are performed against the most specific matching prefix
-// permissions in the Table.
+// permissions in the Collection.
 // SchemaVersion is the version number that the client expects the database
 // to be at. To disable schema version checking, pass -1.
 // NOTE(sadovsky): Currently we send []byte values over the wire for Get, Put,
@@ -6927,9 +6927,9 @@
 // RowServerMethods is the interface a server writer
 // implements for Row.
 //
-// Row represents a single row in a Table.
+// Row represents a single row in a Collection.
 // All access checks are performed against the most specific matching prefix
-// permissions in the Table.
+// permissions in the Collection.
 // SchemaVersion is the version number that the client expects the database
 // to be at. To disable schema version checking, pass -1.
 // NOTE(sadovsky): Currently we send []byte values over the wire for Get, Put,
@@ -7018,7 +7018,7 @@
 var descRow = rpc.InterfaceDesc{
 	Name:    "Row",
 	PkgPath: "v.io/v23/services/syncbase",
-	Doc:     "// Row represents a single row in a Table.\n// All access checks are performed against the most specific matching prefix\n// permissions in the Table.\n// SchemaVersion is the version number that the client expects the database\n// to be at. To disable schema version checking, pass -1.\n// NOTE(sadovsky): Currently we send []byte values over the wire for Get, Put,\n// and Scan. If there's a way to avoid encoding/decoding on the server side, we\n// can use vdl.Value everywhere without sacrificing performance.",
+	Doc:     "// Row represents a single row in a Collection.\n// All access checks are performed against the most specific matching prefix\n// permissions in the Collection.\n// SchemaVersion is the version number that the client expects the database\n// to be at. To disable schema version checking, pass -1.\n// NOTE(sadovsky): Currently we send []byte values over the wire for Get, Put,\n// and Scan. If there's a way to avoid encoding/decoding on the server side, we\n// can use vdl.Value everywhere without sacrificing performance.",
 	Methods: []rpc.MethodDesc{
 		{
 			Name: "Exists",
@@ -7087,7 +7087,7 @@
 	vdl.Register((*BatchOptions)(nil))
 	vdl.Register((*PrefixPermissions)(nil))
 	vdl.Register((*KeyValue)(nil))
-	vdl.Register((*TableRow)(nil))
+	vdl.Register((*CollectionRow)(nil))
 	vdl.Register((*SyncgroupSpec)(nil))
 	vdl.Register((*SyncgroupMemberInfo)(nil))
 	vdl.Register((*ResolverType)(nil))
diff --git a/services/syncbase/types.vdl b/services/syncbase/types.vdl
index b13c5b5..70da265 100644
--- a/services/syncbase/types.vdl
+++ b/services/syncbase/types.vdl
@@ -59,9 +59,9 @@
 	Value []byte
 }
 
-// TableRow encapsulates the table name and row key or row prefix.
-type TableRow struct {
-	TableName string
+// CollectionRow encapsulates the collection name and row key or row prefix.
+type CollectionRow struct {
+	CollectionName string
 	Row       string
 }
 
@@ -73,8 +73,8 @@
 	// Permissions governing access to this syncgroup.
 	Perms access.Permissions
 
-	// Data (tableName-rowPrefix pairs) covered by this syncgroup.
-	Prefixes []TableRow
+	// Data (collectionName-rowPrefix pairs) covered by this syncgroup.
+	Prefixes []CollectionRow
 
 	// Mount tables at which to advertise this syncgroup, for rendezvous purposes.
 	// (Note that in addition to these mount tables, Syncbase also uses
@@ -334,11 +334,11 @@
 // CrRule provides a filter and the type of resolution to perform for a row
 // under conflict that passes the filter.
 type CrRule struct {
-	// TableName is the name of the table that this rule applies to.
-	TableName	string
+	// CollectionName is the name of the collection that this rule applies to.
+	CollectionName string
 
-	// KeyPrefix represents the set of keys within the given table for which
-	// this policy applies. TableName must not be empty if this field is set.
+	// KeyPrefix represents the set of keys within the given collection for which
+	// this policy applies. CollectionName must not be empty if this field is set.
 	KeyPrefix	string
 
 	// Type includes the full package path for the value type for which this
diff --git a/syncbase/.api b/syncbase/.api
index e6a9b8c..db5cadb 100644
--- a/syncbase/.api
+++ b/syncbase/.api
@@ -66,16 +66,16 @@
 pkg syncbase, type App interface, ListDatabases(*context.T) ([]string, error)
 pkg syncbase, type App interface, Name() string
 pkg syncbase, type App interface, unexported methods
-pkg syncbase, type BatchDatabase interface { Abort, Close, Commit, Exec, FullName, GetResumeMarker, ListTables, Name, Table }
+pkg syncbase, type BatchDatabase interface { Abort, Close, Collection, Commit, Exec, FullName, GetResumeMarker, ListCollections, Name }
 pkg syncbase, type BatchDatabase interface, Abort(*context.T) error
 pkg syncbase, type BatchDatabase interface, Close()
+pkg syncbase, type BatchDatabase interface, Collection(string) Collection
 pkg syncbase, type BatchDatabase interface, Commit(*context.T) error
 pkg syncbase, type BatchDatabase interface, Exec(*context.T, string, ...interface{}) ([]string, ResultStream, error)
 pkg syncbase, type BatchDatabase interface, FullName() string
 pkg syncbase, type BatchDatabase interface, GetResumeMarker(*context.T) (watch.ResumeMarker, error)
-pkg syncbase, type BatchDatabase interface, ListTables(*context.T) ([]string, error)
+pkg syncbase, type BatchDatabase interface, ListCollections(*context.T) ([]string, error)
 pkg syncbase, type BatchDatabase interface, Name() string
-pkg syncbase, type BatchDatabase interface, Table(string) Table
 pkg syncbase, type Blob interface { Commit, Delete, Fetch, Get, Keep, Pin, Put, Ref, Size, Unpin }
 pkg syncbase, type Blob interface, Commit(*context.T) error
 pkg syncbase, type Blob interface, Delete(*context.T) error
@@ -101,6 +101,23 @@
 pkg syncbase, type BlobWriter interface, Close() error
 pkg syncbase, type BlobWriter interface, Send([]byte) error
 pkg syncbase, type ChangeType uint32
+pkg syncbase, type Collection interface { Create, Delete, DeletePrefixPermissions, DeleteRange, Destroy, Exists, FullName, Get, GetPermissions, GetPrefixPermissions, Name, Put, Row, Scan, SetPermissions, SetPrefixPermissions }
+pkg syncbase, type Collection interface, Create(*context.T, access.Permissions) error
+pkg syncbase, type Collection interface, Delete(*context.T, string) error
+pkg syncbase, type Collection interface, DeletePrefixPermissions(*context.T, PrefixRange) error
+pkg syncbase, type Collection interface, DeleteRange(*context.T, RowRange) error
+pkg syncbase, type Collection interface, Destroy(*context.T) error
+pkg syncbase, type Collection interface, Exists(*context.T) (bool, error)
+pkg syncbase, type Collection interface, FullName() string
+pkg syncbase, type Collection interface, Get(*context.T, string, interface{}) error
+pkg syncbase, type Collection interface, GetPermissions(*context.T) (access.Permissions, error)
+pkg syncbase, type Collection interface, GetPrefixPermissions(*context.T, string) ([]PrefixPermissions, error)
+pkg syncbase, type Collection interface, Name() string
+pkg syncbase, type Collection interface, Put(*context.T, string, interface{}) error
+pkg syncbase, type Collection interface, Row(string) Row
+pkg syncbase, type Collection interface, Scan(*context.T, RowRange) ScanStream
+pkg syncbase, type Collection interface, SetPermissions(*context.T, access.Permissions) error
+pkg syncbase, type Collection interface, SetPrefixPermissions(*context.T, PrefixRange, access.Permissions) error
 pkg syncbase, type Conflict struct
 pkg syncbase, type Conflict struct, Batches map[uint64]syncbase.BatchInfo
 pkg syncbase, type Conflict struct, ReadSet *ConflictRowSet
@@ -138,6 +155,7 @@
 pkg syncbase, type Database interface, BeginBatch(*context.T, wire.BatchOptions) (BatchDatabase, error)
 pkg syncbase, type Database interface, Blob(wire.BlobRef) Blob
 pkg syncbase, type Database interface, Close()
+pkg syncbase, type Database interface, Collection(string) Collection
 pkg syncbase, type Database interface, Create(*context.T, access.Permissions) error
 pkg syncbase, type Database interface, CreateBlob(*context.T) (Blob, error)
 pkg syncbase, type Database interface, Destroy(*context.T) error
@@ -147,22 +165,21 @@
 pkg syncbase, type Database interface, FullName() string
 pkg syncbase, type Database interface, GetResumeMarker(*context.T) (watch.ResumeMarker, error)
 pkg syncbase, type Database interface, GetSyncgroupNames(*context.T) ([]string, error)
-pkg syncbase, type Database interface, ListTables(*context.T) ([]string, error)
+pkg syncbase, type Database interface, ListCollections(*context.T) ([]string, error)
 pkg syncbase, type Database interface, Name() string
 pkg syncbase, type Database interface, PauseSync(*context.T) error
 pkg syncbase, type Database interface, ResumeSync(*context.T) error
 pkg syncbase, type Database interface, Syncgroup(string) Syncgroup
-pkg syncbase, type Database interface, Table(string) Table
 pkg syncbase, type Database interface, Watch(*context.T, string, string, watch.ResumeMarker) (WatchStream, error)
 pkg syncbase, type Database interface, unexported methods
-pkg syncbase, type DatabaseHandle interface { Close, Exec, FullName, GetResumeMarker, ListTables, Name, Table }
+pkg syncbase, type DatabaseHandle interface { Close, Collection, Exec, FullName, GetResumeMarker, ListCollections, Name }
 pkg syncbase, type DatabaseHandle interface, Close()
+pkg syncbase, type DatabaseHandle interface, Collection(string) Collection
 pkg syncbase, type DatabaseHandle interface, Exec(*context.T, string, ...interface{}) ([]string, ResultStream, error)
 pkg syncbase, type DatabaseHandle interface, FullName() string
 pkg syncbase, type DatabaseHandle interface, GetResumeMarker(*context.T) (watch.ResumeMarker, error)
-pkg syncbase, type DatabaseHandle interface, ListTables(*context.T) ([]string, error)
+pkg syncbase, type DatabaseHandle interface, ListCollections(*context.T) ([]string, error)
 pkg syncbase, type DatabaseHandle interface, Name() string
-pkg syncbase, type DatabaseHandle interface, Table(string) Table
 pkg syncbase, type InvalidScanStream struct
 pkg syncbase, type InvalidScanStream struct, Error error
 pkg syncbase, type PrefixPermissions struct
@@ -226,23 +243,6 @@
 pkg syncbase, type Syncgroup interface, Join(*context.T, wire.SyncgroupMemberInfo) (wire.SyncgroupSpec, error)
 pkg syncbase, type Syncgroup interface, Leave(*context.T) error
 pkg syncbase, type Syncgroup interface, SetSpec(*context.T, wire.SyncgroupSpec, string) error
-pkg syncbase, type Table interface { Create, Delete, DeletePrefixPermissions, DeleteRange, Destroy, Exists, FullName, Get, GetPermissions, GetPrefixPermissions, Name, Put, Row, Scan, SetPermissions, SetPrefixPermissions }
-pkg syncbase, type Table interface, Create(*context.T, access.Permissions) error
-pkg syncbase, type Table interface, Delete(*context.T, string) error
-pkg syncbase, type Table interface, DeletePrefixPermissions(*context.T, PrefixRange) error
-pkg syncbase, type Table interface, DeleteRange(*context.T, RowRange) error
-pkg syncbase, type Table interface, Destroy(*context.T) error
-pkg syncbase, type Table interface, Exists(*context.T) (bool, error)
-pkg syncbase, type Table interface, FullName() string
-pkg syncbase, type Table interface, Get(*context.T, string, interface{}) error
-pkg syncbase, type Table interface, GetPermissions(*context.T) (access.Permissions, error)
-pkg syncbase, type Table interface, GetPrefixPermissions(*context.T, string) ([]PrefixPermissions, error)
-pkg syncbase, type Table interface, Name() string
-pkg syncbase, type Table interface, Put(*context.T, string, interface{}) error
-pkg syncbase, type Table interface, Row(string) Row
-pkg syncbase, type Table interface, Scan(*context.T, RowRange) ScanStream
-pkg syncbase, type Table interface, SetPermissions(*context.T, access.Permissions) error
-pkg syncbase, type Table interface, SetPrefixPermissions(*context.T, PrefixRange, access.Permissions) error
 pkg syncbase, type Value struct
 pkg syncbase, type Value struct, Selection syncbase.ValueSelection
 pkg syncbase, type Value struct, State syncbase.ValueState
@@ -254,11 +254,11 @@
 pkg syncbase, type ValueTarget struct, embedded vdl.TargetBase
 pkg syncbase, type WatchChange struct
 pkg syncbase, type WatchChange struct, ChangeType ChangeType
+pkg syncbase, type WatchChange struct, Collection string
 pkg syncbase, type WatchChange struct, Continued bool
 pkg syncbase, type WatchChange struct, FromSync bool
 pkg syncbase, type WatchChange struct, ResumeMarker watch.ResumeMarker
 pkg syncbase, type WatchChange struct, Row string
-pkg syncbase, type WatchChange struct, Table string
 pkg syncbase, type WatchChange struct, ValueBytes []byte
 pkg syncbase, type WatchStream interface { Advance, Cancel, Change, Err }
 pkg syncbase, type WatchStream interface, Advance() bool
diff --git a/syncbase/batch_test.go b/syncbase/batch_test.go
index 4cae5c9..45a987e 100644
--- a/syncbase/batch_test.go
+++ b/syncbase/batch_test.go
@@ -56,12 +56,12 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{}, []interface{}{})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{}, []interface{}{})
 
 	var b1, b2 syncbase.BatchDatabase
-	var b1tb, b2tb syncbase.Table
+	var b1c, b2c syncbase.Collection
 	var err error
 
 	// Test that the effects of a transaction are not visible until commit.
@@ -69,28 +69,28 @@
 	if err != nil {
 		t.Fatalf("d.BeginBatch() failed: %v", err)
 	}
-	b1tb = b1.Table("tb")
+	b1c = b1.Collection("c")
 
-	if err := b1tb.Put(ctx, "fooKey", "fooValue"); err != nil {
+	if err := b1c.Put(ctx, "fooKey", "fooValue"); err != nil {
 		t.Fatalf("Put() failed: %v", err)
 	}
 
 	// Check that foo is visible inside of this transaction.
-	tu.CheckScan(t, ctx, b1tb, syncbase.Prefix(""), []string{"fooKey"}, []interface{}{"fooValue"})
+	tu.CheckScan(t, ctx, b1c, syncbase.Prefix(""), []string{"fooKey"}, []interface{}{"fooValue"})
 
 	// Check that foo is not yet visible outside of this transaction.
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{}, []interface{}{})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{}, []interface{}{})
 
 	// Start a scan in b1, advance the scan one row, put a new value that would
 	// occur later in the scan (if it were visible) and then advance the scan to see
 	// that it doesn't show (since we snapshot uncommiteed changes at the start).
 	// Ditto for Exec.
 	// start the scan and exec
-	scanIt := b1tb.Scan(ctx, syncbase.Prefix(""))
+	scanIt := b1c.Scan(ctx, syncbase.Prefix(""))
 	if !scanIt.Advance() {
 		t.Fatal("scanIt.Advance() returned false")
 	}
-	_, execIt, err := b1.Exec(ctx, "select k from tb")
+	_, execIt, err := b1.Exec(ctx, "select k from c")
 	if err != nil {
 		t.Fatalf("b1.Exec() failed: %v", err)
 	}
@@ -98,7 +98,7 @@
 		t.Fatal("execIt.Advance() returned false")
 	}
 	// put "zzzKey"
-	if err := b1tb.Put(ctx, "zzzKey", "zzzValue"); err != nil {
+	if err := b1c.Put(ctx, "zzzKey", "zzzValue"); err != nil {
 		t.Fatalf("Put() failed: %v", err)
 	}
 	// make sure Scan's Advance doesn't return a "zzzKey"
@@ -129,7 +129,7 @@
 	}
 
 	// Check that foo is now visible.
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{"fooKey", "zzzKey"}, []interface{}{"fooValue", "zzzValue"})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{"fooKey", "zzzKey"}, []interface{}{"fooValue", "zzzValue"})
 
 	// Test that concurrent transactions are isolated.
 	if b1, err = d.BeginBatch(ctx, wire.BatchOptions{}); err != nil {
@@ -138,20 +138,20 @@
 	if b2, err = d.BeginBatch(ctx, wire.BatchOptions{}); err != nil {
 		t.Fatalf("d.BeginBatch() failed: %v", err)
 	}
-	b1tb, b2tb = b1.Table("tb"), b2.Table("tb")
+	b1c, b2c = b1.Collection("c"), b2.Collection("c")
 
-	if err := b1tb.Put(ctx, "barKey", "barValue"); err != nil {
+	if err := b1c.Put(ctx, "barKey", "barValue"); err != nil {
 		t.Fatalf("Put() failed: %v", err)
 	}
-	if err := b1tb.Put(ctx, "bazKey", "bazValue"); err != nil {
+	if err := b1c.Put(ctx, "bazKey", "bazValue"); err != nil {
 		t.Fatalf("Put() failed: %v", err)
 	}
 
 	var got string
-	if err := b2tb.Get(ctx, "barKey", &got); verror.ErrorID(err) != verror.ErrNoExist.ID {
+	if err := b2c.Get(ctx, "barKey", &got); verror.ErrorID(err) != verror.ErrNoExist.ID {
 		t.Fatalf("Get() should have failed: %v", err)
 	}
-	if err := b2tb.Put(ctx, "rabKey", "rabValue"); err != nil {
+	if err := b2c.Put(ctx, "rabKey", "rabValue"); err != nil {
 		t.Fatalf("Put() failed: %v", err)
 	}
 
@@ -163,46 +163,47 @@
 	}
 
 	// Check that foo, bar, baz and zzz (but not rab) are now visible.
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{"barKey", "bazKey", "fooKey", "zzzKey"}, []interface{}{"barValue", "bazValue", "fooValue", "zzzValue"})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{"barKey", "bazKey", "fooKey", "zzzKey"}, []interface{}{"barValue", "bazValue", "fooValue", "zzzValue"})
 }
 
-// Tests that BatchDatabase.ListTables does not see the effect of concurrent
-// table creation.
-// Note, this test fails if Database.ListTables is implemented using glob,
-// because b.ListTables() does not see "tb". The glob client library issues glob
-// on each point along the path to check for Resolve access. Glob("a") returns
-// "a/d" but not "a/d%%batchInfo", so the glob client library does not recurse
-// further.
-func TestBatchListTables(t *testing.T) {
+// Tests that BatchDatabase.ListCollections does not see the effect of
+// concurrent collection creation.
+
+// Note, this test fails if Database.ListCollections is implemented using glob,
+// because b.ListCollections() does not see "c". The glob client library issues
+// glob on each point along the path to check for Resolve access. Glob("a")
+// returns "a/d" but not "a/d%%batchInfo", so the glob client library does not
+// recurse further.
+func TestBatchListCollections(t *testing.T) {
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tu.CreateTable(t, ctx, d, "tb")
+	tu.CreateCollection(t, ctx, d, "c")
 	b, err := d.BeginBatch(ctx, wire.BatchOptions{})
 
-	got, err := d.ListTables(ctx)
-	want := []string{"tb"}
+	got, err := d.ListCollections(ctx)
+	want := []string{"c"}
 	if err != nil {
-		t.Fatalf("self.ListTables() failed: %v", err)
+		t.Fatalf("self.ListCollections() failed: %v", err)
 	}
 	if !reflect.DeepEqual(got, want) {
 		t.Fatalf("Lists do not match: got %v, want %v", got, want)
 	}
 
-	// Table creation/destruction is not allowed within a batch.
-	if err := b.Table("tb_batch").Create(ctx, nil); verror.ErrorID(err) != wire.ErrBoundToBatch.ID {
-		t.Fatalf("b.tb_batch.Create() should have failed: %v", err)
+	// Collection creation/destruction is not allowed within a batch.
+	if err := b.Collection("c_batch").Create(ctx, nil); verror.ErrorID(err) != wire.ErrBoundToBatch.ID {
+		t.Fatalf("b.c_batch.Create() should have failed: %v", err)
 	}
-	if err := b.Table("tb").Destroy(ctx); verror.ErrorID(err) != wire.ErrBoundToBatch.ID {
-		t.Fatalf("b.tb.Destroy() should have failed: %v", err)
+	if err := b.Collection("c").Destroy(ctx); verror.ErrorID(err) != wire.ErrBoundToBatch.ID {
+		t.Fatalf("b.c.Destroy() should have failed: %v", err)
 	}
 
-	tu.CreateTable(t, ctx, d, "tb_nonbatch")
+	tu.CreateCollection(t, ctx, d, "c_nonbatch")
 
-	// Non-batch should see tb_nonbatch; batch should only see tb.
-	got, err = d.ListTables(ctx)
-	want = []string{"tb", "tb_nonbatch"}
+	// Non-batch should see c_nonbatch; batch should only see c.
+	got, err = d.ListCollections(ctx)
+	want = []string{"c", "c_nonbatch"}
 	if err != nil {
 		t.Fatalf("self.ListChildren() failed: %v", err)
 	}
@@ -210,8 +211,8 @@
 		t.Fatalf("Lists do not match: got %v, want %v", got, want)
 	}
 
-	got, err = b.ListTables(ctx)
-	want = []string{"tb"}
+	got, err = b.ListCollections(ctx)
+	want = []string{"c"}
 	if err != nil {
 		t.Fatalf("self.ListChildren() failed: %v", err)
 	}
@@ -223,34 +224,34 @@
 // Tests that BatchDatabase.Exec doesn't see changes committed outside the
 // batch.
 // 1. Create a read only batch.
-// 2. query all rows in the table
+// 2. query all rows in the collection
 // 3. commit a new row outside of the batch
-// 4. confirm new row not seen when querying all rows in the table
+// 4. confirm new row not seen when querying all rows in the collection
 // 5. abort the batch and create a new readonly batch
-// 6. confirm new row NOW seen when querying all rows in the table
+// 6. confirm new row NOW seen when querying all rows in the collection
 func TestBatchExecIsolation(t *testing.T) {
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
 	foo := Foo{I: 4, S: "f"}
-	if err := tb.Put(ctx, "foo", foo); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "foo", foo); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	bar := Bar{F: 0.5, S: "b"}
 	// NOTE: not best practice, but store bar as
 	// optional (by passing the address of bar to Put).
 	// This tests auto-dereferencing.
-	if err := tb.Put(ctx, "bar", &bar); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "bar", &bar); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	baz := Baz{Name: "John Doe", Active: true}
-	if err := tb.Put(ctx, "baz", baz); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "baz", baz); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	// Begin a readonly batch.
@@ -260,7 +261,7 @@
 	}
 
 	// fetch all rows
-	tu.CheckExec(t, ctx, roBatch, "select k, v from tb",
+	tu.CheckExec(t, ctx, roBatch, "select k, v from c",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("bar"), vom.RawBytesOf(bar)},
@@ -270,12 +271,12 @@
 
 	// Add a row outside this batch
 	newRow := Baz{Name: "Alice Wonderland", Active: false}
-	if err := tb.Put(ctx, "newRow", newRow); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "newRow", newRow); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	// confirm fetching all rows doesn't get the new row
-	tu.CheckExec(t, ctx, roBatch, "select k, v from tb",
+	tu.CheckExec(t, ctx, roBatch, "select k, v from c",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("bar"), vom.RawBytesOf(bar)},
@@ -292,7 +293,7 @@
 	defer roBatch.Abort(ctx)
 
 	// confirm fetching all rows NOW gets the new row
-	tu.CheckExec(t, ctx, roBatch, "select k, v from tb",
+	tu.CheckExec(t, ctx, roBatch, "select k, v from c",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("bar"), vom.RawBytesOf(bar)},
@@ -311,24 +312,24 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
 	foo := Foo{I: 4, S: "f"}
-	if err := tb.Put(ctx, "foo", foo); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "foo", foo); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	bar := Bar{F: 0.5, S: "b"}
 	// NOTE: not best practice, but store bar as
 	// optional (by passing the address of bar to Put).
 	// This tests auto-dereferencing.
-	if err := tb.Put(ctx, "bar", &bar); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "bar", &bar); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	baz := Baz{Name: "John Doe", Active: true}
-	if err := tb.Put(ctx, "baz", baz); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "baz", baz); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	// Begin a readonly batch.
@@ -338,7 +339,7 @@
 	}
 
 	// Attempt to delete "foo" k/v pair with a syncQL delete.
-	tu.CheckExecError(t, ctx, roBatch, "delete from tb where k = \"foo\"", syncql.ErrTableCantAccess.ID)
+	tu.CheckExecError(t, ctx, roBatch, "delete from c where k = \"foo\"", syncql.ErrTableCantAccess.ID)
 
 	// start a new batch
 	roBatch.Abort(ctx)
@@ -351,24 +352,24 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
 	foo := Foo{I: 4, S: "f"}
-	if err := tb.Put(ctx, "foo", foo); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "foo", foo); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	bar := Bar{F: 0.5, S: "b"}
 	// NOTE: not best practice, but store bar as
 	// optional (by passing the address of bar to Put).
 	// This tests auto-dereferencing.
-	if err := tb.Put(ctx, "bar", &bar); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "bar", &bar); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	baz := Baz{Name: "John Doe", Active: true}
-	if err := tb.Put(ctx, "baz", baz); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "baz", baz); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	// Begin a readwrite batch.
@@ -378,7 +379,7 @@
 	}
 
 	// fetch all rows
-	tu.CheckExec(t, ctx, rwBatch, "select k, v from tb",
+	tu.CheckExec(t, ctx, rwBatch, "select k, v from c",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("bar"), vom.RawBytesOf(bar)},
@@ -386,7 +387,7 @@
 			{vom.RawBytesOf("foo"), vom.RawBytesOf(foo)},
 		})
 
-	rwBatchTb := rwBatch.Table("tb")
+	rwBatchTb := rwBatch.Collection("c")
 
 	// Add a row in this batch
 	newRow := Baz{Name: "Snow White", Active: true}
@@ -395,7 +396,7 @@
 	}
 
 	// confirm fetching all rows DOES get the new row
-	tu.CheckExec(t, ctx, rwBatch, "select k, v from tb",
+	tu.CheckExec(t, ctx, rwBatch, "select k, v from c",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("bar"), vom.RawBytesOf(bar)},
@@ -407,16 +408,16 @@
 	// Delete the first row (bar) and the last row (newRow).
 	// Change the baz row.  Confirm these rows are no longer fetched and that
 	// the change to baz is seen.
-	tu.CheckExec(t, ctx, rwBatch, "delete from tb where k = \"bar\" or k = \"newRow\"",
+	tu.CheckExec(t, ctx, rwBatch, "delete from c where k = \"bar\" or k = \"newRow\"",
 		[]string{"Count"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf(2)},
 		})
 	baz2 := Baz{Name: "Batman", Active: false}
 	if err := rwBatchTb.Put(ctx, "baz", baz2); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+		t.Fatalf("c.Put() failed: %v", err)
 	}
-	tu.CheckExec(t, ctx, rwBatch, "select k, v from tb",
+	tu.CheckExec(t, ctx, rwBatch, "select k, v from c",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("baz"), vom.RawBytesOf(baz2)},
@@ -435,12 +436,12 @@
 	if err := rwBatchTb.Put(ctx, "newRow", newRow2); err != nil {
 		t.Fatalf("rwBatchTb.Put() failed: %v", err)
 	}
-	tu.CheckExec(t, ctx, rwBatch, "delete from tb where k = \"baz\" or k = \"foo\"",
+	tu.CheckExec(t, ctx, rwBatch, "delete from c where k = \"baz\" or k = \"foo\"",
 		[]string{"Count"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf(2)},
 		})
-	tu.CheckExec(t, ctx, rwBatch, "select k, v from tb",
+	tu.CheckExec(t, ctx, rwBatch, "select k, v from c",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("bar"), vom.RawBytesOf(bar2)},
@@ -458,7 +459,7 @@
 	defer roBatch.Abort(ctx)
 
 	// confirm fetching all rows gets the rows committed above
-	tu.CheckExec(t, ctx, roBatch, "select k, v from tb",
+	tu.CheckExec(t, ctx, roBatch, "select k, v from c",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("bar"), vom.RawBytesOf(bar2)},
@@ -472,25 +473,25 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
-	if err := tb.Put(ctx, "fooKey", "fooValue"); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "fooKey", "fooValue"); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	b1, err := d.BeginBatch(ctx, wire.BatchOptions{ReadOnly: true})
 	if err != nil {
 		t.Fatalf("d.BeginBatch() failed: %v", err)
 	}
-	b1tb := b1.Table("tb")
+	b1c := b1.Collection("c")
 
-	if err := b1tb.Put(ctx, "barKey", "barValue"); verror.ErrorID(err) != wire.ErrReadOnlyBatch.ID {
+	if err := b1c.Put(ctx, "barKey", "barValue"); verror.ErrorID(err) != wire.ErrReadOnlyBatch.ID {
 		t.Fatalf("Put() should have failed: %v", err)
 	}
-	if err := b1tb.DeleteRange(ctx, syncbase.Prefix("fooKey")); verror.ErrorID(err) != wire.ErrReadOnlyBatch.ID {
-		t.Fatalf("Table.DeleteRange() should have failed: %v", err)
+	if err := b1c.DeleteRange(ctx, syncbase.Prefix("fooKey")); verror.ErrorID(err) != wire.ErrReadOnlyBatch.ID {
+		t.Fatalf("Collection.DeleteRange() should have failed: %v", err)
 	}
-	if err := b1tb.Row("fooKey").Delete(ctx); verror.ErrorID(err) != wire.ErrReadOnlyBatch.ID {
+	if err := b1c.Row("fooKey").Delete(ctx); verror.ErrorID(err) != wire.ErrReadOnlyBatch.ID {
 		t.Fatalf("Row.Delete() should have failed: %v", err)
 	}
 }
@@ -501,28 +502,28 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
 	// TODO(sadovsky): Add some sort of "op after finalize" error type and check
 	// for it specifically below.
 	checkOpsFail := func(b syncbase.BatchDatabase) {
-		btb := b.Table("tb")
+		bc := b.Collection("c")
 		var got string
-		if err := btb.Get(ctx, "fooKey", &got); err == nil {
+		if err := bc.Get(ctx, "fooKey", &got); err == nil {
 			tu.Fatal(t, "Get() should have failed")
 		}
-		it := btb.Scan(ctx, syncbase.Prefix(""))
+		it := bc.Scan(ctx, syncbase.Prefix(""))
 		it.Advance()
 		if it.Err() == nil {
 			tu.Fatal(t, "Scan() should have failed")
 		}
-		if err := btb.Put(ctx, "barKey", "barValue"); err == nil {
+		if err := bc.Put(ctx, "barKey", "barValue"); err == nil {
 			tu.Fatal(t, "Put() should have failed")
 		}
-		if err := btb.DeleteRange(ctx, syncbase.Prefix("fooKey")); err == nil {
-			tu.Fatal(t, "Table.DeleteRange() should have failed: %v", err)
+		if err := bc.DeleteRange(ctx, syncbase.Prefix("fooKey")); err == nil {
+			tu.Fatal(t, "Collection.DeleteRange() should have failed: %v", err)
 		}
-		if err := btb.Row("fooKey").Delete(ctx); err == nil {
+		if err := bc.Row("fooKey").Delete(ctx); err == nil {
 			tu.Fatal(t, "Row.Delete() should have failed: %v", err)
 		}
 		if err := b.Commit(ctx); err == nil {
@@ -535,9 +536,9 @@
 	if err != nil {
 		t.Fatalf("d.BeginBatch() failed: %v", err)
 	}
-	b1tb := b1.Table("tb")
+	b1c := b1.Collection("c")
 
-	if err := b1tb.Put(ctx, "fooKey", "fooValue"); err != nil {
+	if err := b1c.Put(ctx, "fooKey", "fooValue"); err != nil {
 		t.Fatalf("Put() failed: %v", err)
 	}
 	if err := b1.Commit(ctx); err != nil {
@@ -550,15 +551,15 @@
 	if b1, err = d.BeginBatch(ctx, wire.BatchOptions{}); err != nil {
 		t.Fatalf("d.BeginBatch() failed: %v", err)
 	}
-	b1tb = b1.Table("tb")
+	b1c = b1.Collection("c")
 
-	// Conflicts with future b1tb.Get().
-	if err := tb.Put(ctx, "fooKey", "v2"); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	// Conflicts with future b1c.Get().
+	if err := c.Put(ctx, "fooKey", "v2"); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	var got string
-	if err := b1tb.Get(ctx, "fooKey", &got); err != nil {
+	if err := b1c.Get(ctx, "fooKey", &got); err != nil {
 		t.Fatalf("Get() failed: %v", err)
 	}
 	want := "fooValue"
@@ -575,7 +576,7 @@
 	if b1, err = d.BeginBatch(ctx, wire.BatchOptions{}); err != nil {
 		t.Fatalf("d.BeginBatch() failed: %v", err)
 	}
-	b1tb = b1.Table("tb")
+	b1c = b1.Collection("c")
 	b1.Abort(ctx)
 	checkOpsFail(b1)
 }
@@ -627,8 +628,8 @@
 		t.Fatalf("bc.GetSyncgroupNames() should have failed: %v", err)
 	}
 
-	// Test that Table.{Create,Destroy} fail with ErrBoundToBatch.
-	tc := wire.TableClient(naming.Join(b.FullName(), "tb"))
+	// Test that Collection.{Create,Destroy} fail with ErrBoundToBatch.
+	tc := wire.CollectionClient(naming.Join(b.FullName(), "c"))
 	if err := tc.Create(ctx, -1, nil); verror.ErrorID(err) != wire.ErrBoundToBatch.ID {
 		t.Fatalf("tc.Create() should have failed: %v", err)
 	}
@@ -656,18 +657,18 @@
 	return syncbase.RunInBatch(ctx, d, wire.BatchOptions{}, func(b syncbase.BatchDatabase) error {
 		retries++
 		// Read foo.
-		if err := b.Table("tb").Get(ctx, fmt.Sprintf("foo-%d", retries), &value); verror.ErrorID(err) != verror.ErrNoExist.ID {
+		if err := b.Collection("c").Get(ctx, fmt.Sprintf("foo-%d", retries), &value); verror.ErrorID(err) != verror.ErrNoExist.ID {
 			t.Errorf("b.Get() should have failed with ErrNoExist, got: %v", err)
 		}
 		// If we need to fail, write to foo in a separate concurrent batch. This
 		// is always written on every attempt.
 		if retries < failTimes {
-			if err := d.Table("tb").Put(ctx, fmt.Sprintf("foo-%d", retries), "foo"); err != nil {
+			if err := d.Collection("c").Put(ctx, fmt.Sprintf("foo-%d", retries), "foo"); err != nil {
 				t.Errorf("d.Put() failed: %v", err)
 			}
 		}
 		// Write to bar. This is only committed on a successful attempt.
-		if err := b.Table("tb").Put(ctx, fmt.Sprintf("bar-%d", retries), "bar"); err != nil {
+		if err := b.Collection("c").Put(ctx, fmt.Sprintf("bar-%d", retries), "bar"); err != nil {
 			t.Errorf("b.Put() failed: %v", err)
 		}
 		// Return user defined error.
@@ -681,14 +682,14 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
 	// Succeed (no conflict) on second try.
 	if err := tryWithConcurrentWrites(t, ctx, d, 2, nil); err != nil {
 		t.Errorf("RunInBatch() failed: %v", err)
 	}
 	// First try failed, second succeeded.
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""),
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""),
 		[]string{"bar-2", "foo-1"},
 		[]interface{}{"bar", "foo"})
 }
@@ -699,7 +700,7 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
 	// Succeed (no conflict) on 10th try. RunInBatch will retry 3 times and give
 	// up with ErrConcurrentBatch.
@@ -707,7 +708,7 @@
 		t.Errorf("RunInBatch() should have failed with ErrConcurrentBatch, got: %v", err)
 	}
 	// Three failed tries.
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""),
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""),
 		[]string{"foo-1", "foo-2", "foo-3"},
 		[]interface{}{"foo", "foo", "foo"})
 }
@@ -718,7 +719,7 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
 	// Return error from fn. Errors other than ErrConcurrentTransaction are not
 	// retried.
@@ -727,7 +728,7 @@
 		t.Errorf("RunInBatch() should have failed with %v, got: %v", dummyError, err)
 	}
 	// Single failed try.
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""),
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""),
 		[]string{"foo-1"},
 		[]interface{}{"foo"})
 }
@@ -738,35 +739,35 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
 	// Test readonly batch.
-	if err := tb.Put(ctx, "foo", 1); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "foo", 1); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 	if err := syncbase.RunInBatch(ctx, d, wire.BatchOptions{ReadOnly: true}, func(b syncbase.BatchDatabase) error {
 		var value int32
 		// Read foo.
-		if err := b.Table("tb").Get(ctx, "foo", &value); err != nil {
+		if err := b.Collection("c").Get(ctx, "foo", &value); err != nil {
 			t.Fatalf("b.Get() failed: %v", err)
 		}
 		newValue := value + 1
 		// Write to foo in a separate concurrent batch. This is always written on
 		// every iteration. It should not cause a retry since readonly batches are
 		// not committed.
-		if err := d.Table("tb").Put(ctx, "foo", newValue); err != nil {
+		if err := d.Collection("c").Put(ctx, "foo", newValue); err != nil {
 			t.Errorf("d.Put() failed: %v", err)
 		}
 		// Read foo again. Batch should not see the incremented value.
 		var rereadValue int32
-		if err := b.Table("tb").Get(ctx, "foo", &rereadValue); err != nil {
+		if err := b.Collection("c").Get(ctx, "foo", &rereadValue); err != nil {
 			t.Fatalf("b.Get() failed: %v", err)
 		}
 		if value != rereadValue {
 			t.Fatal("batch should not see value change outside batch")
 		}
 		// Try writing to bar. This should fail since the batch is readonly.
-		if err := b.Table("tb").Put(ctx, "bar", value); verror.ErrorID(err) != wire.ErrReadOnlyBatch.ID {
+		if err := b.Collection("c").Put(ctx, "bar", value); verror.ErrorID(err) != wire.ErrReadOnlyBatch.ID {
 			t.Errorf("b.Put() should have failed with ErrReadOnlyBatch, got: %v", err)
 		}
 		return nil
@@ -774,7 +775,7 @@
 		t.Errorf("RunInBatch() failed: %v", err)
 	}
 	// Single uncommitted iteration.
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""),
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""),
 		[]string{"foo"},
 		[]interface{}{int32(2)})
 }
diff --git a/syncbase/benchmark_test.go b/syncbase/benchmark_test.go
index a966b32..8087560 100644
--- a/syncbase/benchmark_test.go
+++ b/syncbase/benchmark_test.go
@@ -39,9 +39,9 @@
 	tu "v.io/x/ref/services/syncbase/testutil"
 )
 
-// prepare creates hierarchy "a/d/tb" and returns some handles along with a
+// prepare creates hierarchy "a/d/c" and returns some handles along with a
 // cleanup function.
-func prepare(b *testing.B) (*context.T, syncbase.Database, syncbase.Table, func()) {
+func prepare(b *testing.B) (*context.T, syncbase.Database, syncbase.Collection, func()) {
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	s := syncbase.NewService(sName)
 	a := s.App("a")
@@ -52,11 +52,11 @@
 	if err := d.Create(ctx, nil); err != nil {
 		b.Fatalf("can't create database: %v", err)
 	}
-	tb := d.Table("tb")
-	if err := tb.Create(ctx, nil); err != nil {
-		b.Fatalf("can't create table: %v", err)
+	c := d.Collection("c")
+	if err := c.Create(ctx, nil); err != nil {
+		b.Fatalf("can't create collection: %v", err)
 	}
-	return ctx, d, tb, func() {
+	return ctx, d, c, func() {
 		b.StopTimer()
 		cleanup()
 		b.StartTimer()
@@ -92,46 +92,46 @@
 	return testStruct{A: "hello, world!", B: 42, D: byteSlice}
 }
 
-func writeRows(b *testing.B, ctx *context.T, tb syncbase.Table, value interface{}) {
-	writeRowsCustom(b, ctx, tb, value, b.N)
+func writeRows(b *testing.B, ctx *context.T, c syncbase.Collection, value interface{}) {
+	writeRowsCustom(b, ctx, c, value, b.N)
 }
 
-func writeRowsCustom(b *testing.B, ctx *context.T, tb syncbase.Table, value interface{}, n int) {
+func writeRowsCustom(b *testing.B, ctx *context.T, c syncbase.Collection, value interface{}, n int) {
 	for i := 0; i < n; i++ {
-		if err := tb.Put(ctx, makeKey(i), value); err != nil {
+		if err := c.Put(ctx, makeKey(i), value); err != nil {
 			b.Fatal(err)
 		}
 	}
 }
 
 func runPutBenchmark(b *testing.B, value interface{}) {
-	ctx, _, tb, cleanup := prepare(b)
+	ctx, _, c, cleanup := prepare(b)
 	defer cleanup()
 	b.ResetTimer()
-	writeRows(b, ctx, tb, value)
+	writeRows(b, ctx, c, value)
 }
 
 func runGetBenchmark(b *testing.B, value interface{}) {
-	ctx, _, tb, cleanup := prepare(b)
+	ctx, _, c, cleanup := prepare(b)
 	defer cleanup()
-	writeRows(b, ctx, tb, value)
+	writeRows(b, ctx, c, value)
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		var got testStruct
-		if err := tb.Get(ctx, makeKey(i), &got); err != nil {
-			b.Fatalf("tb.Get failed: %v", err)
+		if err := c.Get(ctx, makeKey(i), &got); err != nil {
+			b.Fatalf("c.Get failed: %v", err)
 		}
 	}
 }
 
 func runDeleteBenchmark(b *testing.B, value interface{}) {
-	ctx, _, tb, cleanup := prepare(b)
+	ctx, _, c, cleanup := prepare(b)
 	defer cleanup()
-	writeRows(b, ctx, tb, value)
+	writeRows(b, ctx, c, value)
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		if err := tb.Delete(ctx, makeKey(i)); err != nil {
-			b.Fatalf("tb.Delete failed: %v", err)
+		if err := c.Delete(ctx, makeKey(i)); err != nil {
+			b.Fatalf("c.Delete failed: %v", err)
 		}
 	}
 }
@@ -140,16 +140,16 @@
 
 // Measures how long it takes to process 'numRows' rows using scan.
 func runScanBenchmark(b *testing.B, value interface{}) {
-	ctx, _, tb, cleanup := prepare(b)
+	ctx, _, c, cleanup := prepare(b)
 	defer cleanup()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		b.StopTimer()
 		// TODO(sadovsky): Write rows just once, and clear any read caches on every
 		// iteration.
-		writeRowsCustom(b, ctx, tb, value, numRows)
+		writeRowsCustom(b, ctx, c, value, numRows)
 		b.StartTimer()
-		s := tb.Scan(ctx, syncbase.Prefix(""))
+		s := c.Scan(ctx, syncbase.Prefix(""))
 		var got testStruct
 		for s.Advance() {
 			s.Value(&got)
@@ -162,16 +162,16 @@
 
 // Measures how long it takes to process 'numRows' rows using exec.
 func runExecBenchmark(b *testing.B, value interface{}) {
-	ctx, d, tb, cleanup := prepare(b)
+	ctx, d, c, cleanup := prepare(b)
 	defer cleanup()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
 		b.StopTimer()
 		// TODO(sadovsky): Write rows just once, and clear any read caches on every
 		// iteration.
-		writeRowsCustom(b, ctx, tb, value, numRows)
+		writeRowsCustom(b, ctx, c, value, numRows)
 		b.StartTimer()
-		_, s, err := d.Exec(ctx, "select v from tb")
+		_, s, err := d.Exec(ctx, "select v from c")
 		if err != nil {
 			b.Fatalf("exec error: %s", s.Err())
 		}
@@ -187,11 +187,11 @@
 // Measures how long it takes to put and get notified about 'numRows' rows.
 func runWatchPutsBenchmark(b *testing.B, value interface{}) {
 	b.Skip("Hangs on occasion, for unknown reasons - v.io/i/1134")
-	ctx, d, tb, cleanup := prepare(b)
+	ctx, d, c, cleanup := prepare(b)
 	defer cleanup()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		w, err := d.Watch(ctx, "tb", "", watch.ResumeMarker("now"))
+		w, err := d.Watch(ctx, "c", "", watch.ResumeMarker("now"))
 		if err != nil {
 			b.Fatalf("watch error: %v", err)
 		}
@@ -207,7 +207,7 @@
 			}
 			close(done)
 		}()
-		writeRowsCustom(b, ctx, tb, value, numRows)
+		writeRowsCustom(b, ctx, c, value, numRows)
 		<-done
 		w.Cancel()
 	}
@@ -216,9 +216,9 @@
 // Measures how long it takes to put and get notified about a single value.
 func runWatchOnePutBenchmark(b *testing.B, value interface{}) {
 	b.Skip("Hangs on occasion, for unknown reasons - v.io/i/1134")
-	ctx, d, tb, cleanup := prepare(b)
+	ctx, d, c, cleanup := prepare(b)
 	defer cleanup()
-	w, err := d.Watch(ctx, "tb", "", watch.ResumeMarker("now"))
+	w, err := d.Watch(ctx, "c", "", watch.ResumeMarker("now"))
 	row := make(chan struct{})
 	if err != nil {
 		b.Fatalf("watch error: %v", err)
@@ -236,7 +236,7 @@
 	}()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		writeRowsCustom(b, ctx, tb, value, 1)
+		writeRowsCustom(b, ctx, c, value, 1)
 		<-row
 	}
 	w.Cancel()
diff --git a/syncbase/client_test.go b/syncbase/client_test.go
index b806a97..49ce91a 100644
--- a/syncbase/client_test.go
+++ b/syncbase/client_test.go
@@ -31,8 +31,8 @@
 	s := syncbase.NewService("s")
 	a := s.App("a")
 	d := a.Database("d", nil)
-	tb := d.Table("tb")
-	r := tb.Row("r")
+	c := d.Collection("c")
+	r := c.Row("r")
 
 	if s.FullName() != "s" {
 		t.Errorf("Wrong full name: %q", s.FullName())
@@ -49,16 +49,16 @@
 	if d.FullName() != naming.Join("s", "a", "d") {
 		t.Errorf("Wrong full name: %q", d.FullName())
 	}
-	if tb.Name() != "tb" {
-		t.Errorf("Wrong name: %q", tb.Name())
+	if c.Name() != "c" {
+		t.Errorf("Wrong name: %q", c.Name())
 	}
-	if tb.FullName() != naming.Join("s", "a", "d", "tb") {
-		t.Errorf("Wrong full name: %q", tb.FullName())
+	if c.FullName() != naming.Join("s", "a", "d", "c") {
+		t.Errorf("Wrong full name: %q", c.FullName())
 	}
 	if r.Key() != "r" {
 		t.Errorf("Wrong key: %q", r.Key())
 	}
-	if r.FullName() != naming.Join("s", "a", "d", "tb", "r") {
+	if r.FullName() != naming.Join("s", "a", "d", "c", "r") {
 		t.Errorf("Wrong full name: %q", r.FullName())
 	}
 }
@@ -104,7 +104,7 @@
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "app/a#%b")
-	tu.TestListChildren(t, ctx, a, tu.OkDbTableNames)
+	tu.TestListChildren(t, ctx, a, tu.OkDbCollectionNames)
 }
 
 // Tests that App.{Set,Get}Permissions work as expected.
@@ -123,28 +123,28 @@
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
 	d2 := tu.CreateDatabase(t, ctx, a, "d2")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 	// Write some data.
-	if err := tb.Put(ctx, "bar/baz", "A"); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "bar/baz", "A"); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
-	if err := tb.Put(ctx, "foo", "B"); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "foo", "B"); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 	// Remove admin and write permissions from "bar" and d2.
 	fullPerms := tu.DefaultPerms("root:client").Normalize()
 	readPerms := fullPerms.Copy()
 	readPerms.Clear("root:client", string(access.Write), string(access.Admin))
 	readPerms.Normalize()
-	if err := tb.SetPrefixPermissions(ctx, syncbase.Prefix("bar"), readPerms); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(ctx, syncbase.Prefix("bar"), readPerms); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
 	if err := d2.SetPermissions(ctx, readPerms, ""); err != nil {
 		t.Fatalf("d2.SetPermissions() failed: %v", err)
 	}
 	// Verify we have no write access to "bar" anymore.
-	if err := tb.Put(ctx, "bar/bat", "C"); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.Put() should have failed with ErrNoAccess, got: %v", err)
+	if err := c.Put(ctx, "bar/bat", "C"); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.Put() should have failed with ErrNoAccess, got: %v", err)
 	}
 	// Verify we cannot destroy d2.
 	if err := d2.Destroy(ctx); verror.ErrorID(err) != verror.ErrNoAccess.ID {
@@ -159,12 +159,12 @@
 	a = tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d = tu.CreateDatabase(t, ctx, a, "d")
 	d2 = tu.CreateDatabase(t, ctx, a, "d2")
-	tb = tu.CreateTable(t, ctx, d, "tb")
-	// Verify table is empty.
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{}, []interface{}{})
+	c = tu.CreateCollection(t, ctx, d, "c")
+	// Verify collection is empty.
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{}, []interface{}{})
 	// Verify we again have write access to "bar".
-	if err := tb.Put(ctx, "bar/bat", "C"); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "bar/bat", "C"); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 }
 
@@ -181,7 +181,7 @@
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
-	tu.TestCreateNameValidation(t, ctx, a, tu.OkDbTableNames, tu.NotOkDbTableNames)
+	tu.TestCreateNameValidation(t, ctx, a, tu.OkDbCollectionNames, tu.NotOkDbCollectionNames)
 }
 
 // Tests that Database.Destroy works as expected.
@@ -200,33 +200,33 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
 	foo := Foo{I: 4, S: "f"}
-	if err := tb.Put(ctx, "foo", foo); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "foo", foo); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	bar := Bar{F: 0.5, S: "b"}
 	// NOTE: not best practice, but store bar as
 	// optional (by passing the address of bar to Put).
 	// This tests auto-dereferencing.
-	if err := tb.Put(ctx, "bar", &bar); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "bar", &bar); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	baz := Baz{Name: "John Doe", Active: true}
-	if err := tb.Put(ctx, "baz", baz); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "baz", baz); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
-	tu.CheckExec(t, ctx, d, "select k, v.Name from tb where Type(v) like \"%.Baz\"",
+	tu.CheckExec(t, ctx, d, "select k, v.Name from c where Type(v) like \"%.Baz\"",
 		[]string{"k", "v.Name"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("baz"), vom.RawBytesOf(baz.Name)},
 		})
 
-	tu.CheckExec(t, ctx, d, "select k, v from tb",
+	tu.CheckExec(t, ctx, d, "select k, v from c",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("bar"), vom.RawBytesOf(bar)},
@@ -234,46 +234,46 @@
 			{vom.RawBytesOf("foo"), vom.RawBytesOf(foo)},
 		})
 
-	tu.CheckExec(t, ctx, d, "select k, v from tb where k like \"ba%\"",
+	tu.CheckExec(t, ctx, d, "select k, v from c where k like \"ba%\"",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("bar"), vom.RawBytesOf(bar)},
 			{vom.RawBytesOf("baz"), vom.RawBytesOf(baz)},
 		})
 
-	tu.CheckExec(t, ctx, d, "select k, v from tb where v.Active = true",
+	tu.CheckExec(t, ctx, d, "select k, v from c where v.Active = true",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("baz"), vom.RawBytesOf(baz)},
 		})
 
-	tu.CheckExec(t, ctx, d, "select k, v from tb where Type(v) like \"%.Bar\"",
+	tu.CheckExec(t, ctx, d, "select k, v from c where Type(v) like \"%.Bar\"",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("bar"), vom.RawBytesOf(bar)},
 		})
 
-	tu.CheckExec(t, ctx, d, "select k, v from tb where v.F = 0.5",
+	tu.CheckExec(t, ctx, d, "select k, v from c where v.F = 0.5",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("bar"), vom.RawBytesOf(bar)},
 		})
 
-	tu.CheckExec(t, ctx, d, "select k, v from tb where Type(v) like \"%.Baz\"",
+	tu.CheckExec(t, ctx, d, "select k, v from c where Type(v) like \"%.Baz\"",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("baz"), vom.RawBytesOf(baz)},
 		})
 
-	// Delete baz
-	tu.CheckExec(t, ctx, d, "delete from tb where Type(v) like \"%.Baz\"",
+	// Delete baz.
+	tu.CheckExec(t, ctx, d, "delete from c where Type(v) like \"%.Baz\"",
 		[]string{"Count"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf(1)},
 		})
 
-	// Check that bas is no longer in the table.
-	tu.CheckExec(t, ctx, d, "select k, v from tb",
+	// Check that baz is no longer in the collection.
+	tu.CheckExec(t, ctx, d, "select k, v from c",
 		[]string{"k", "v"},
 		[][]*vom.RawBytes{
 			{vom.RawBytesOf("bar"), vom.RawBytesOf(bar)},
@@ -283,13 +283,13 @@
 	tu.CheckExecError(t, ctx, d, "select k, v from foo", syncql.ErrTableCantAccess.ID)
 }
 
-// Tests that Database.ListTables works as expected.
-func TestListTables(t *testing.T) {
+// Tests that Database.ListCollections works as expected.
+func TestListCollections(t *testing.T) {
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "app/a#%b")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tu.TestListChildren(t, ctx, d, tu.OkDbTableNames)
+	tu.TestListChildren(t, ctx, d, tu.OkDbCollectionNames)
 }
 
 // Tests that Database.{Set,Get}Permissions work as expected.
@@ -301,8 +301,8 @@
 	tu.TestPerms(t, ctx, d)
 }
 
-// Tests that Table.Create works as expected.
-func TestTableCreate(t *testing.T) {
+// Tests that Collection.Create works as expected.
+func TestCollectionCreate(t *testing.T) {
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
@@ -310,17 +310,17 @@
 	tu.TestCreate(t, ctx, d)
 }
 
-// Tests name-checking on table creation.
-func TestTableCreateNameValidation(t *testing.T) {
+// Tests name-checking on collection creation.
+func TestCollectionCreateNameValidation(t *testing.T) {
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tu.TestCreateNameValidation(t, ctx, d, tu.OkDbTableNames, tu.NotOkDbTableNames)
+	tu.TestCreateNameValidation(t, ctx, d, tu.OkDbCollectionNames, tu.NotOkDbCollectionNames)
 }
 
-// Tests that Table.Destroy works as expected.
-func TestTableDestroy(t *testing.T) {
+// Tests that Collection.Destroy works as expected.
+func TestCollectionDestroy(t *testing.T) {
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
@@ -328,14 +328,14 @@
 	tu.TestDestroy(t, ctx, d)
 }
 
-// Tests that Table.{Set,Get,Delete}Permissions methods work as expected.
-func TestTablePerms(t *testing.T) {
+// Tests that Collection.{Set,Get,Delete}Permissions methods work as expected.
+func TestCollectionPerms(t *testing.T) {
 	ctx, clientACtx, sName, rootp, cleanup := tu.SetupOrDieCustom("clientA", "server", nil)
 	defer cleanup()
 	clientBCtx := tu.NewCtx(ctx, rootp, "clientB")
 	a := tu.CreateApp(t, clientACtx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, clientACtx, a, "d")
-	tb := tu.CreateTable(t, clientACtx, d, "tb")
+	c := tu.CreateCollection(t, clientACtx, d, "c")
 
 	// Permission objects.
 	aAndB := tu.DefaultPerms("root:clientA", "root:clientB")
@@ -343,57 +343,57 @@
 	bOnly := tu.DefaultPerms("root:clientB")
 
 	// Set initial permissions.
-	if err := tb.SetPermissions(clientACtx, aAndB); err != nil {
-		t.Fatalf("tb.SetPermissions() failed: %v", err)
+	if err := c.SetPermissions(clientACtx, aAndB); err != nil {
+		t.Fatalf("c.SetPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), aAndB); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), aAndB); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix("prefix"), aAndB); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix("prefix"), aAndB); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientBCtx, syncbase.Prefix("prefix"), aAndB); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientBCtx, syncbase.Prefix("prefix"), aAndB); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix("prefix_a"), aOnly); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix("prefix_a"), aOnly); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientBCtx, syncbase.Prefix("prefix_b"), bOnly); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientBCtx, syncbase.Prefix("prefix_b"), bOnly); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
 
 	// Checks A has no access to 'prefix_b' and vice versa.
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix("prefix_b"), aOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.SetPrefixPermissions() should have failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix("prefix_b"), aOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.SetPrefixPermissions() should have failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix("prefix_b_suffix"), aOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.SetPrefixPermissions() should have failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix("prefix_b_suffix"), aOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.SetPrefixPermissions() should have failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientBCtx, syncbase.Prefix("prefix_a"), bOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.SetPrefixPermissions() should have failed: %v", err)
+	if err := c.SetPrefixPermissions(clientBCtx, syncbase.Prefix("prefix_a"), bOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.SetPrefixPermissions() should have failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientBCtx, syncbase.Prefix("prefix_a_suffix"), bOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.SetPrefixPermissions() should have failed: %v", err)
+	if err := c.SetPrefixPermissions(clientBCtx, syncbase.Prefix("prefix_a_suffix"), bOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.SetPrefixPermissions() should have failed: %v", err)
 	}
 
 	// Check GetPrefixPermissions.
 	wantPerms := []syncbase.PrefixPermissions{
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix(""), Perms: aAndB},
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, ""); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, ""); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "abc"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "abc"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
 	wantPerms = []syncbase.PrefixPermissions{
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix("prefix"), Perms: aAndB},
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix(""), Perms: aAndB},
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_c"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_c"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
 	wantPerms = []syncbase.PrefixPermissions{
@@ -401,10 +401,10 @@
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix("prefix"), Perms: aAndB},
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix(""), Perms: aAndB},
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_a"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_a"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_a_suffix"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_a_suffix"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
 	wantPerms = []syncbase.PrefixPermissions{
@@ -412,89 +412,89 @@
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix("prefix"), Perms: aAndB},
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix(""), Perms: aAndB},
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_b"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_b"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_b_suffix"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_b_suffix"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
 
 	// Delete some prefix permissions and check again.
 	// Check that A can't delete permissions of B.
-	if err := tb.DeletePrefixPermissions(clientACtx, syncbase.Prefix("prefix_b")); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.DeletePrefixPermissions() should have failed: %v", err)
+	if err := c.DeletePrefixPermissions(clientACtx, syncbase.Prefix("prefix_b")); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.DeletePrefixPermissions() should have failed: %v", err)
 	}
-	if err := tb.DeletePrefixPermissions(clientBCtx, syncbase.Prefix("prefix_a")); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.DeletePrefixPermissions() should have failed: %v", err)
+	if err := c.DeletePrefixPermissions(clientBCtx, syncbase.Prefix("prefix_a")); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.DeletePrefixPermissions() should have failed: %v", err)
 	}
 	// Delete 'prefix' and 'prefix_a'
-	if err := tb.DeletePrefixPermissions(clientACtx, syncbase.Prefix("prefix")); err != nil {
-		t.Fatalf("tb.DeletePrefixPermissions() failed: %v", err)
+	if err := c.DeletePrefixPermissions(clientACtx, syncbase.Prefix("prefix")); err != nil {
+		t.Fatalf("c.DeletePrefixPermissions() failed: %v", err)
 	}
-	if err := tb.DeletePrefixPermissions(clientACtx, syncbase.Prefix("prefix_a")); err != nil {
-		t.Fatalf("tb.DeletePrefixPermissions() failed: %v", err)
+	if err := c.DeletePrefixPermissions(clientACtx, syncbase.Prefix("prefix_a")); err != nil {
+		t.Fatalf("c.DeletePrefixPermissions() failed: %v", err)
 	}
 	// Check DeletePrefixPermissions is idempotent.
-	if err := tb.DeletePrefixPermissions(clientACtx, syncbase.Prefix("prefix")); err != nil {
-		t.Fatalf("tb.DeletePrefixPermissions() failed: %v", err)
+	if err := c.DeletePrefixPermissions(clientACtx, syncbase.Prefix("prefix")); err != nil {
+		t.Fatalf("c.DeletePrefixPermissions() failed: %v", err)
 	}
 
 	// Check GetPrefixPermissions again.
 	wantPerms = []syncbase.PrefixPermissions{
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix(""), Perms: aAndB},
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, ""); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, ""); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_a"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_a"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_a_suffix"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_a_suffix"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
 	wantPerms = []syncbase.PrefixPermissions{
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix("prefix_b"), Perms: bOnly},
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix(""), Perms: aAndB},
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_b"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_b"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_b_suffix"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_b_suffix"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
 
-	// Remove B from table-level permissions and check B has no access.
-	if err := tb.SetPermissions(clientACtx, aOnly); err != nil {
-		t.Fatalf("tb.SetPermissions() failed: %v", err)
+	// Remove B from collection-level permissions and check B has no access.
+	if err := c.SetPermissions(clientACtx, aOnly); err != nil {
+		t.Fatalf("c.SetPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), aOnly); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), aOnly); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if _, err := tb.GetPrefixPermissions(clientBCtx, ""); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.GetPrefixPermissions() should have failed: %v", err)
+	if _, err := c.GetPrefixPermissions(clientBCtx, ""); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.GetPrefixPermissions() should have failed: %v", err)
 	}
-	if _, err := tb.GetPrefixPermissions(clientBCtx, "prefix_b"); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.GetPrefixPermissions() should have failed: %v", err)
+	if _, err := c.GetPrefixPermissions(clientBCtx, "prefix_b"); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.GetPrefixPermissions() should have failed: %v", err)
 	}
-	if err := tb.SetPermissions(clientBCtx, bOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.SetPermissions() should have failed: %v", err)
+	if err := c.SetPermissions(clientBCtx, bOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.SetPermissions() should have failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientBCtx, syncbase.Prefix("prefix_b"), bOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.SetPrefixPermissions() should have failed: %v", err)
+	if err := c.SetPrefixPermissions(clientBCtx, syncbase.Prefix("prefix_b"), bOnly); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.SetPrefixPermissions() should have failed: %v", err)
 	}
 }
 
-// Tests that Table.{Set,Get}Permissions methods work as expected.
-func TestTablePermsDifferentOrder(t *testing.T) {
+// Tests that Collection.{Set,Get}Permissions methods work as expected.
+func TestCollectionPermsDifferentOrder(t *testing.T) {
 	ctx, clientACtx, sName, rootp, cleanup := tu.SetupOrDieCustom("clientA", "server", nil)
 	defer cleanup()
 	clientBCtx := tu.NewCtx(ctx, rootp, "clientB")
 	a := tu.CreateApp(t, clientACtx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, clientACtx, a, "d")
-	tb := tu.CreateTable(t, clientACtx, d, "tb")
+	c := tu.CreateCollection(t, clientACtx, d, "c")
 
 	// Permission objects.
 	aAndB := tu.DefaultPerms("root:clientA", "root:clientB")
@@ -502,20 +502,20 @@
 	bOnly := tu.DefaultPerms("root:clientB")
 
 	// Set initial permissions.
-	if err := tb.SetPermissions(clientACtx, aAndB); err != nil {
-		t.Fatalf("tb.SetPermissions() failed: %v", err)
+	if err := c.SetPermissions(clientACtx, aAndB); err != nil {
+		t.Fatalf("c.SetPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), aAndB); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), aAndB); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix("prefix"), aAndB); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix("prefix"), aAndB); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientBCtx, syncbase.Prefix("prefix_b"), bOnly); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientBCtx, syncbase.Prefix("prefix_b"), bOnly); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix("prefix_a"), aOnly); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix("prefix_a"), aOnly); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
 
 	wantPerms := []syncbase.PrefixPermissions{
@@ -523,10 +523,10 @@
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix("prefix"), Perms: aAndB},
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix(""), Perms: aAndB},
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_a"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_a"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_a_suffix"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_a_suffix"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
 	wantPerms = []syncbase.PrefixPermissions{
@@ -534,10 +534,10 @@
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix("prefix"), Perms: aAndB},
 		syncbase.PrefixPermissions{Prefix: syncbase.Prefix(""), Perms: aAndB},
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_b"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_b"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
-	if got, _ := tb.GetPrefixPermissions(clientACtx, "prefix_b_suffix"); !reflect.DeepEqual(got, wantPerms) {
+	if got, _ := c.GetPrefixPermissions(clientACtx, "prefix_b_suffix"); !reflect.DeepEqual(got, wantPerms) {
 		t.Fatalf("Unexpected permissions: got %v, want %v", got, wantPerms)
 	}
 }
@@ -554,7 +554,7 @@
 	return prefix
 }
 
-func checkGetPermissions(t *testing.T, ctx *context.T, tb syncbase.Table, prefix string, max, min int) {
+func checkGetPermissions(t *testing.T, ctx *context.T, c syncbase.Collection, prefix string, max, min int) {
 	perms := tu.DefaultPerms("root:client")
 	for len(prefix) < max {
 		prefix += "a"
@@ -564,19 +564,19 @@
 		wantPerms = append(wantPerms, syncbase.PrefixPermissions{Prefix: syncbase.Prefix(prefix[:k]), Perms: perms})
 	}
 	wantPerms = append(wantPerms, syncbase.PrefixPermissions{Prefix: syncbase.Prefix(""), Perms: perms})
-	if gotPerms, _ := tb.GetPrefixPermissions(ctx, prefix); !reflect.DeepEqual(gotPerms, wantPerms) {
+	if gotPerms, _ := c.GetPrefixPermissions(ctx, prefix); !reflect.DeepEqual(gotPerms, wantPerms) {
 		tu.Fatalf(t, "Unexpected permissions for %q: got %v, want %v", prefix, gotPerms, wantPerms)
 	}
 }
 
-// Tests that Table.{Set,Get,Delete}Permissions methods work as expected
+// Tests that Collection.{Set,Get,Delete}Permissions methods work as expected
 // for nested prefixes.
-func TestTablePermsNested(t *testing.T) {
+func TestCollectionPermsNested(t *testing.T) {
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 	// The permission object.
 	perms := tu.DefaultPerms("root:client")
 	depth := 4
@@ -584,83 +584,83 @@
 	for i := 1; i <= depth; i++ {
 		for j := 0; j < 1<<uint32(i); j++ {
 			prefix := bitmaskToPrefix(j, i)
-			if err := tb.SetPrefixPermissions(ctx, syncbase.Prefix(prefix), perms); err != nil {
-				t.Fatalf("tb.SetPrefixPermissions() failed for %q: %v", prefix, err)
+			if err := c.SetPrefixPermissions(ctx, syncbase.Prefix(prefix), perms); err != nil {
+				t.Fatalf("c.SetPrefixPermissions() failed for %q: %v", prefix, err)
 			}
-			checkGetPermissions(t, ctx, tb, prefix, i, 1)
+			checkGetPermissions(t, ctx, c, prefix, i, 1)
 		}
 	}
 	// Delete permissions in the reverse order.
 	for i := depth; i >= 1; i-- {
 		for j := 0; j < 1<<uint32(i); j++ {
 			prefix := bitmaskToPrefix(j, i)
-			if err := tb.DeletePrefixPermissions(ctx, syncbase.Prefix(prefix)); err != nil {
-				t.Fatalf("tb.DeletePrefixPermissions() failed for %q: %v", prefix, err)
+			if err := c.DeletePrefixPermissions(ctx, syncbase.Prefix(prefix)); err != nil {
+				t.Fatalf("c.DeletePrefixPermissions() failed for %q: %v", prefix, err)
 			}
-			checkGetPermissions(t, ctx, tb, prefix, i-1, 1)
+			checkGetPermissions(t, ctx, c, prefix, i-1, 1)
 		}
 	}
 	// Do again the first two steps in the reverse order.
 	for i := depth; i >= 1; i-- {
 		for j := 0; j < 1<<uint32(i); j++ {
 			prefix := bitmaskToPrefix(j, i)
-			if err := tb.SetPrefixPermissions(ctx, syncbase.Prefix(prefix), perms); err != nil {
-				t.Fatalf("tb.SetPrefixPermissions() failed for %q: %v", prefix, err)
+			if err := c.SetPrefixPermissions(ctx, syncbase.Prefix(prefix), perms); err != nil {
+				t.Fatalf("c.SetPrefixPermissions() failed for %q: %v", prefix, err)
 			}
-			checkGetPermissions(t, ctx, tb, prefix, depth, i)
+			checkGetPermissions(t, ctx, c, prefix, depth, i)
 		}
 	}
 	for i := 1; i <= depth; i++ {
 		for j := 0; j < 1<<uint32(i); j++ {
 			prefix := bitmaskToPrefix(j, i)
-			if err := tb.DeletePrefixPermissions(ctx, syncbase.Prefix(prefix)); err != nil {
-				t.Fatalf("tb.DeletePrefixPermissions() failed for %q: %v", prefix, err)
+			if err := c.DeletePrefixPermissions(ctx, syncbase.Prefix(prefix)); err != nil {
+				t.Fatalf("c.DeletePrefixPermissions() failed for %q: %v", prefix, err)
 			}
-			checkGetPermissions(t, ctx, tb, prefix, depth, i+1)
+			checkGetPermissions(t, ctx, c, prefix, depth, i+1)
 		}
 	}
 }
 
-// Tests that Table.Destroy deletes all rows and ACLs in the table.
-func TestTableDestroyAndRecreate(t *testing.T) {
+// Tests that Collection.Destroy deletes all rows and ACLs in the collection.
+func TestCollectionDestroyAndRecreate(t *testing.T) {
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 	// Write some data.
-	if err := tb.Put(ctx, "bar/baz", "A"); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "bar/baz", "A"); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
-	if err := tb.Put(ctx, "foo", "B"); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "foo", "B"); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 	// Remove admin and write permissions from "bar".
 	fullPerms := tu.DefaultPerms("root:client").Normalize()
 	readPerms := fullPerms.Copy()
 	readPerms.Clear("root:client", string(access.Write), string(access.Admin))
 	readPerms.Normalize()
-	if err := tb.SetPrefixPermissions(ctx, syncbase.Prefix("bar"), readPerms); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(ctx, syncbase.Prefix("bar"), readPerms); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
 	// Verify we have no write access to "bar" anymore.
-	if err := tb.Put(ctx, "bar/bat", "C"); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.Put() should have failed with ErrNoAccess, got: %v", err)
+	if err := c.Put(ctx, "bar/bat", "C"); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.Put() should have failed with ErrNoAccess, got: %v", err)
 	}
-	// Destroy table. Destroy needs only admin permissions on the table, so it
-	// shouldn't be affected by the read-only prefix ACL.
-	if err := tb.Destroy(ctx); err != nil {
-		t.Fatalf("tb.Destroy() failed: %v", err)
+	// Destroy collection. Destroy needs only admin permissions on the collection,
+	// so it shouldn't be affected by the read-only prefix ACL.
+	if err := c.Destroy(ctx); err != nil {
+		t.Fatalf("c.Destroy() failed: %v", err)
 	}
-	// Recreate the table.
-	if err := tb.Create(ctx, nil); err != nil {
-		t.Fatalf("tb.Create() (recreate) failed: %v", err)
+	// Recreate the collection.
+	if err := c.Create(ctx, nil); err != nil {
+		t.Fatalf("c.Create() (recreate) failed: %v", err)
 	}
-	// Verify table is empty.
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{}, []interface{}{})
+	// Verify collection is empty.
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{}, []interface{}{})
 	// Verify we again have write access to "bar".
-	if err := tb.Put(ctx, "bar/bat", "C"); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "bar/bat", "C"); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 }
 
@@ -682,127 +682,127 @@
 	Active bool
 }
 
-// Tests that Table.Scan works as expected.
-func TestTableScan(t *testing.T) {
+// Tests that Collection.Scan works as expected.
+func TestCollectionScan(t *testing.T) {
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{}, []interface{}{})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{}, []interface{}{})
 
 	fooWant := Foo{I: 4, S: "f"}
-	if err := tb.Put(ctx, "foo", &fooWant); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "foo", &fooWant); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 	barWant := Bar{F: 0.5, S: "b"}
-	if err := tb.Put(ctx, "bar", &barWant); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "bar", &barWant); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	// Match all keys.
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
-	tu.CheckScan(t, ctx, tb, syncbase.Range("", ""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
-	tu.CheckScan(t, ctx, tb, syncbase.Range("", "z"), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
-	tu.CheckScan(t, ctx, tb, syncbase.Range("a", ""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
-	tu.CheckScan(t, ctx, tb, syncbase.Range("a", "z"), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
+	tu.CheckScan(t, ctx, c, syncbase.Range("", ""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
+	tu.CheckScan(t, ctx, c, syncbase.Range("", "z"), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
+	tu.CheckScan(t, ctx, c, syncbase.Range("a", ""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
+	tu.CheckScan(t, ctx, c, syncbase.Range("a", "z"), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
 
 	// Match "bar" only.
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix("b"), []string{"bar"}, []interface{}{&barWant})
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix("bar"), []string{"bar"}, []interface{}{&barWant})
-	tu.CheckScan(t, ctx, tb, syncbase.Range("bar", "baz"), []string{"bar"}, []interface{}{&barWant})
-	tu.CheckScan(t, ctx, tb, syncbase.Range("bar", "foo"), []string{"bar"}, []interface{}{&barWant})
-	tu.CheckScan(t, ctx, tb, syncbase.Range("", "foo"), []string{"bar"}, []interface{}{&barWant})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix("b"), []string{"bar"}, []interface{}{&barWant})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix("bar"), []string{"bar"}, []interface{}{&barWant})
+	tu.CheckScan(t, ctx, c, syncbase.Range("bar", "baz"), []string{"bar"}, []interface{}{&barWant})
+	tu.CheckScan(t, ctx, c, syncbase.Range("bar", "foo"), []string{"bar"}, []interface{}{&barWant})
+	tu.CheckScan(t, ctx, c, syncbase.Range("", "foo"), []string{"bar"}, []interface{}{&barWant})
 
 	// Match "foo" only.
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix("f"), []string{"foo"}, []interface{}{&fooWant})
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix("foo"), []string{"foo"}, []interface{}{&fooWant})
-	tu.CheckScan(t, ctx, tb, syncbase.Range("foo", "fox"), []string{"foo"}, []interface{}{&fooWant})
-	tu.CheckScan(t, ctx, tb, syncbase.Range("foo", ""), []string{"foo"}, []interface{}{&fooWant})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix("f"), []string{"foo"}, []interface{}{&fooWant})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix("foo"), []string{"foo"}, []interface{}{&fooWant})
+	tu.CheckScan(t, ctx, c, syncbase.Range("foo", "fox"), []string{"foo"}, []interface{}{&fooWant})
+	tu.CheckScan(t, ctx, c, syncbase.Range("foo", ""), []string{"foo"}, []interface{}{&fooWant})
 
 	// Match nothing.
-	tu.CheckScan(t, ctx, tb, syncbase.Range("a", "bar"), []string{}, []interface{}{})
-	tu.CheckScan(t, ctx, tb, syncbase.Range("bar", "bar"), []string{}, []interface{}{})
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix("z"), []string{}, []interface{}{})
+	tu.CheckScan(t, ctx, c, syncbase.Range("a", "bar"), []string{}, []interface{}{})
+	tu.CheckScan(t, ctx, c, syncbase.Range("bar", "bar"), []string{}, []interface{}{})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix("z"), []string{}, []interface{}{})
 }
 
-// Tests that Table.DeleteRange works as expected.
-func TestTableDeleteRange(t *testing.T) {
+// Tests that Collection.DeleteRange works as expected.
+func TestCollectionDeleteRange(t *testing.T) {
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{}, []interface{}{})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{}, []interface{}{})
 
 	// Put foo and bar.
 	fooWant := Foo{I: 4, S: "f"}
-	if err := tb.Put(ctx, "foo", &fooWant); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "foo", &fooWant); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 	barWant := Bar{F: 0.5, S: "b"}
-	if err := tb.Put(ctx, "bar", &barWant); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "bar", &barWant); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
 
 	// Delete foo.
-	if err := tb.DeleteRange(ctx, syncbase.Prefix("f")); err != nil {
-		t.Fatalf("tb.DeleteRange() failed: %v", err)
+	if err := c.DeleteRange(ctx, syncbase.Prefix("f")); err != nil {
+		t.Fatalf("c.DeleteRange() failed: %v", err)
 	}
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{"bar"}, []interface{}{&barWant})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{"bar"}, []interface{}{&barWant})
 
 	// Restore foo.
-	if err := tb.Put(ctx, "foo", &fooWant); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "foo", &fooWant); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{"bar", "foo"}, []interface{}{&barWant, &fooWant})
 
 	// Delete everything.
-	if err := tb.DeleteRange(ctx, syncbase.Prefix("")); err != nil {
-		t.Fatalf("tb.DeleteRange() failed: %v", err)
+	if err := c.DeleteRange(ctx, syncbase.Prefix("")); err != nil {
+		t.Fatalf("c.DeleteRange() failed: %v", err)
 	}
-	tu.CheckScan(t, ctx, tb, syncbase.Prefix(""), []string{}, []interface{}{})
+	tu.CheckScan(t, ctx, c, syncbase.Prefix(""), []string{}, []interface{}{})
 }
 
-// Tests that Table.{Get,Put,Delete} work as expected.
-func TestTableRowMethods(t *testing.T) {
+// Tests that Collection.{Get,Put,Delete} work as expected.
+func TestCollectionRowMethods(t *testing.T) {
 	ctx, sName, cleanup := tu.SetupOrDie(nil)
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
 	got, want := Foo{}, Foo{I: 4, S: "foo"}
-	if err := tb.Get(ctx, "f", &got); verror.ErrorID(err) != verror.ErrNoExist.ID {
-		t.Fatalf("tb.Get() should have failed: %v", err)
+	if err := c.Get(ctx, "f", &got); verror.ErrorID(err) != verror.ErrNoExist.ID {
+		t.Fatalf("c.Get() should have failed: %v", err)
 	}
-	if err := tb.Put(ctx, "f", &want); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "f", &want); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
-	if err := tb.Get(ctx, "f", &got); err != nil {
-		t.Fatalf("tb.Get() failed: %v", err)
+	if err := c.Get(ctx, "f", &got); err != nil {
+		t.Fatalf("c.Get() failed: %v", err)
 	}
 	if !reflect.DeepEqual(got, want) {
 		t.Fatalf("Values do not match: got %v, want %v", got, want)
 	}
 	// Overwrite value.
 	want.I = 6
-	if err := tb.Put(ctx, "f", &want); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, "f", &want); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
-	if err := tb.Get(ctx, "f", &got); err != nil {
-		t.Fatalf("tb.Get() failed: %v", err)
+	if err := c.Get(ctx, "f", &got); err != nil {
+		t.Fatalf("c.Get() failed: %v", err)
 	}
 	if !reflect.DeepEqual(got, want) {
 		t.Fatalf("Values do not match: got %v, want %v", got, want)
 	}
-	if err := tb.Delete(ctx, "f"); err != nil {
-		t.Fatalf("tb.Delete() failed: %v", err)
+	if err := c.Delete(ctx, "f"); err != nil {
+		t.Fatalf("c.Delete() failed: %v", err)
 	}
-	if err := tb.Get(ctx, "f", &got); verror.ErrorID(err) != verror.ErrNoExist.ID {
+	if err := c.Get(ctx, "f", &got); verror.ErrorID(err) != verror.ErrNoExist.ID {
 		t.Fatalf("r.Get() should have failed: %v", err)
 	}
 }
@@ -813,9 +813,9 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
-	r := tb.Row("f")
+	r := c.Row("f")
 	got, want := Foo{}, Foo{I: 4, S: "foo"}
 	if err := r.Get(ctx, &got); verror.ErrorID(err) != verror.ErrNoExist.ID {
 		t.Fatalf("r.Get() should have failed: %v", err)
@@ -854,19 +854,19 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
-	tu.TestCreateNameValidation(t, ctx, tb, tu.OkRowNames, tu.NotOkRowNames)
+	c := tu.CreateCollection(t, ctx, d, "c")
+	tu.TestCreateNameValidation(t, ctx, c, tu.OkRowNames, tu.NotOkRowNames)
 }
 
 // Test permission checking in Row.{Get,Put,Delete} and
-// Table.{Scan, DeleteRange}.
+// Collection.{Scan, DeleteRange}.
 func TestRowPermissions(t *testing.T) {
 	ctx, clientACtx, sName, rootp, cleanup := tu.SetupOrDieCustom("clientA", "server", nil)
 	defer cleanup()
 	clientBCtx := tu.NewCtx(ctx, rootp, "clientB")
 	a := tu.CreateApp(t, clientACtx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, clientACtx, a, "d")
-	tb := tu.CreateTable(t, clientACtx, d, "tb")
+	c := tu.CreateCollection(t, clientACtx, d, "c")
 
 	// Permission objects.
 	aAndB := tu.DefaultPerms("root:clientA", "root:clientB")
@@ -874,22 +874,22 @@
 	bOnly := tu.DefaultPerms("root:clientB")
 
 	// Set initial permissions.
-	if err := tb.SetPermissions(clientACtx, aAndB); err != nil {
-		t.Fatalf("tb.SetPermissions() failed: %v", err)
+	if err := c.SetPermissions(clientACtx, aAndB); err != nil {
+		t.Fatalf("c.SetPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), aAndB); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), aAndB); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix("a"), aOnly); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix("a"), aOnly); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientBCtx, syncbase.Prefix("b"), bOnly); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientBCtx, syncbase.Prefix("b"), bOnly); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
 
 	// Add some key-value pairs.
-	ra := tb.Row("afoo")
-	rb := tb.Row("bfoo")
+	ra := c.Row("afoo")
+	rb := c.Row("bfoo")
 	if err := ra.Put(clientACtx, Foo{}); err != nil {
 		t.Fatalf("ra.Put() failed: %v", err)
 	}
@@ -907,11 +907,11 @@
 	if err := rb.Delete(clientACtx); verror.ErrorID(err) != verror.ErrNoAccess.ID {
 		t.Fatalf("rb.Delete() should have failed: %v", err)
 	}
-	// Test Table.DeleteRange and Scan.
-	if err := tb.DeleteRange(clientACtx, syncbase.Prefix("")); verror.ErrorID(err) != verror.ErrNoAccess.ID {
-		t.Fatalf("tb.DeleteRange should have failed: %v", err)
+	// Test Collection.DeleteRange and Scan.
+	if err := c.DeleteRange(clientACtx, syncbase.Prefix("")); verror.ErrorID(err) != verror.ErrNoAccess.ID {
+		t.Fatalf("c.DeleteRange should have failed: %v", err)
 	}
-	s := tb.Scan(clientACtx, syncbase.Prefix(""))
+	s := c.Scan(clientACtx, syncbase.Prefix(""))
 	if !s.Advance() {
 		t.Fatalf("Stream should have advanced: %v", s.Err())
 	}
@@ -933,7 +933,7 @@
 	clientBCtx := tu.NewCtx(ctx, rootp, "clientB")
 	a := tu.CreateApp(t, clientACtx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, clientACtx, a, "d")
-	tb := tu.CreateTable(t, clientACtx, d, "tb")
+	c := tu.CreateCollection(t, clientACtx, d, "c")
 
 	// Permission objects.
 	aAndB := tu.DefaultPerms("root:clientA", "root:clientB")
@@ -941,18 +941,18 @@
 	aAllBRead.Add(security.BlessingPattern("root:clientB"), string(access.Read))
 
 	// Set initial permissions.
-	if err := tb.SetPermissions(clientACtx, aAndB); err != nil {
-		t.Fatalf("tb.SetPermissions() failed: %v", err)
+	if err := c.SetPermissions(clientACtx, aAndB); err != nil {
+		t.Fatalf("c.SetPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), aAndB); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), aAndB); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix("a"), aAllBRead); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix("a"), aAllBRead); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
 
 	// Both A and B can read and write row key "z".
-	r := tb.Row("z")
+	r := c.Row("z")
 	if err := r.Put(clientACtx, Foo{}); err != nil {
 		t.Fatalf("client A r.Put() failed: %v", err)
 	}
@@ -967,7 +967,7 @@
 	}
 
 	// Both A and B can read row key "a", but only A can write it.
-	r = tb.Row("a")
+	r = c.Row("a")
 	if err := r.Put(clientACtx, Foo{}); err != nil {
 		t.Fatalf("client A r.Put() failed: %v", err)
 	}
@@ -982,7 +982,7 @@
 	}
 
 	// Same for a:foo.
-	r = tb.Row("a:foo")
+	r = c.Row("a:foo")
 	if err := r.Put(clientACtx, Foo{}); err != nil {
 		t.Fatalf("client A r.Put() failed: %v", err)
 	}
@@ -1006,7 +1006,7 @@
 	clientBCtx := tu.NewCtx(ctx, rootp, "clientB")
 	a := tu.CreateApp(t, clientACtx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, clientACtx, a, "d")
-	tb := tu.CreateTable(t, clientACtx, d, "tb")
+	c := tu.CreateCollection(t, clientACtx, d, "c")
 
 	// On "", resolve should be open, and only A should have read/write/admin.
 	// On "b", read/resolve should be open, and only B should have write/admin.
@@ -1021,15 +1021,15 @@
 
 	// Set initial permissions.
 	aAndB := tu.DefaultPerms("root:clientA", "root:clientB")
-	if err := tb.SetPermissions(clientACtx, aAndB); err != nil {
-		t.Fatalf("tb.SetPermissions() failed: %v", err)
+	if err := c.SetPermissions(clientACtx, aAndB); err != nil {
+		t.Fatalf("c.SetPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), prefixEmpty); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), prefixEmpty); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
 	// Note that with the current perms, A must write these perms on B's behalf.
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix("b"), prefixB); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix("b"), prefixB); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
 
 	// A should be able to read/write "a".
@@ -1037,7 +1037,7 @@
 	// B should not be able to read/write "a".
 	// A should not be able to write "b", but should be able to read it.
 
-	r := tb.Row("a")
+	r := c.Row("a")
 	if err := r.Put(clientACtx, Foo{}); err != nil {
 		t.Fatalf("client A r.Put() failed: %v", err)
 	}
@@ -1045,7 +1045,7 @@
 		t.Fatalf("client A r.Get() failed: %v", err)
 	}
 
-	r = tb.Row("b")
+	r = c.Row("b")
 	if err := r.Put(clientBCtx, Foo{}); err != nil {
 		t.Fatalf("client B r.Put() failed: %v", err)
 	}
@@ -1053,7 +1053,7 @@
 		t.Fatalf("client B r.Get() failed: %v", err)
 	}
 
-	r = tb.Row("a")
+	r = c.Row("a")
 	if err := r.Put(clientBCtx, Foo{}); verror.ErrorID(err) != verror.ErrNoAccess.ID {
 		t.Fatalf("client B r.Put() should have failed: %v", err)
 	}
@@ -1061,7 +1061,7 @@
 		t.Fatalf("client B r.Get() should have failed: %v", err)
 	}
 
-	r = tb.Row("b")
+	r = c.Row("b")
 	if err := r.Put(clientACtx, Foo{}); verror.ErrorID(err) != verror.ErrNoAccess.ID {
 		t.Fatalf("client A r.Put() should have failed: %v", err)
 	}
@@ -1077,7 +1077,7 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 	var resumeMarkers []watch.ResumeMarker
 
 	// Generate the data and resume markers.
@@ -1088,7 +1088,7 @@
 	}
 	resumeMarkers = append(resumeMarkers, resumeMarker)
 	// Put "abc".
-	r := tb.Row("abc")
+	r := c.Row("abc")
 	if err := r.Put(ctx, "value"); err != nil {
 		t.Fatalf("r.Put() failed: %v", err)
 	}
@@ -1105,7 +1105,7 @@
 	}
 	resumeMarkers = append(resumeMarkers, resumeMarker)
 	// Put "a".
-	r = tb.Row("a")
+	r = c.Row("a")
 	if err := r.Put(ctx, "value"); err != nil {
 		t.Fatalf("r.Put() failed: %v", err)
 	}
@@ -1117,20 +1117,20 @@
 	vomValue, _ := vom.Encode("value")
 	allChanges := []syncbase.WatchChange{
 		syncbase.WatchChange{
-			Table:        "tb",
+			Collection:   "c",
 			Row:          "abc",
 			ChangeType:   syncbase.PutChange,
 			ValueBytes:   vomValue,
 			ResumeMarker: resumeMarkers[1],
 		},
 		syncbase.WatchChange{
-			Table:        "tb",
+			Collection:   "c",
 			Row:          "abc",
 			ChangeType:   syncbase.DeleteChange,
 			ResumeMarker: resumeMarkers[2],
 		},
 		syncbase.WatchChange{
-			Table:        "tb",
+			Collection:   "c",
 			Row:          "a",
 			ChangeType:   syncbase.PutChange,
 			ValueBytes:   vomValue,
@@ -1139,16 +1139,16 @@
 	}
 	ctxWithTimeout, cancel := context.WithTimeout(ctx, 10*time.Second)
 	defer cancel()
-	wstream, _ := d.Watch(ctxWithTimeout, "tb", "a", resumeMarkers[0])
+	wstream, _ := d.Watch(ctxWithTimeout, "c", "a", resumeMarkers[0])
 	tu.CheckWatch(t, wstream, allChanges)
-	wstream, _ = d.Watch(ctxWithTimeout, "tb", "a", resumeMarkers[1])
+	wstream, _ = d.Watch(ctxWithTimeout, "c", "a", resumeMarkers[1])
 	tu.CheckWatch(t, wstream, allChanges[1:])
-	wstream, _ = d.Watch(ctxWithTimeout, "tb", "a", resumeMarkers[2])
+	wstream, _ = d.Watch(ctxWithTimeout, "c", "a", resumeMarkers[2])
 	tu.CheckWatch(t, wstream, allChanges[2:])
 
-	wstream, _ = d.Watch(ctxWithTimeout, "tb", "abc", resumeMarkers[0])
+	wstream, _ = d.Watch(ctxWithTimeout, "c", "abc", resumeMarkers[0])
 	tu.CheckWatch(t, wstream, allChanges[:2])
-	wstream, _ = d.Watch(ctxWithTimeout, "tb", "abc", resumeMarkers[1])
+	wstream, _ = d.Watch(ctxWithTimeout, "c", "abc", resumeMarkers[1])
 	tu.CheckWatch(t, wstream, allChanges[1:2])
 }
 
@@ -1160,19 +1160,19 @@
 	clientBCtx := tu.NewCtx(ctx, rootp, "clientB")
 	a := tu.CreateApp(t, clientACtx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, clientACtx, a, "d")
-	tb := tu.CreateTable(t, clientACtx, d, "tb")
+	c := tu.CreateCollection(t, clientACtx, d, "c")
 
 	// Set initial permissions.
 	aAndB := tu.DefaultPerms("root:clientA", "root:clientB")
 	aOnly := tu.DefaultPerms("root:clientA")
-	if err := tb.SetPermissions(clientACtx, aAndB); err != nil {
-		t.Fatalf("tb.SetPermissions() failed: %v", err)
+	if err := c.SetPermissions(clientACtx, aAndB); err != nil {
+		t.Fatalf("c.SetPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), aAndB); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix(""), aAndB); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(clientACtx, syncbase.Prefix("a"), aOnly); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(clientACtx, syncbase.Prefix("a"), aOnly); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
 	// Get the initial resume marker.
 	resumeMarker, err := d.GetResumeMarker(clientACtx)
@@ -1182,11 +1182,11 @@
 	initMarker := resumeMarker
 	// Do two puts in a batch.
 	if err := syncbase.RunInBatch(clientACtx, d, wire.BatchOptions{}, func(b syncbase.BatchDatabase) error {
-		tb := b.Table("tb")
-		if err := tb.Put(clientACtx, "a", "value"); err != nil {
+		c := b.Collection("c")
+		if err := c.Put(clientACtx, "a", "value"); err != nil {
 			return err
 		}
-		return tb.Put(clientACtx, "b", "value")
+		return c.Put(clientACtx, "b", "value")
 	}); err != nil {
 		t.Fatalf("RunInBatch failed: %v", err)
 	}
@@ -1197,7 +1197,7 @@
 	vomValue, _ := vom.Encode("value")
 	allChanges := []syncbase.WatchChange{
 		syncbase.WatchChange{
-			Table:        "tb",
+			Collection:   "c",
 			Row:          "a",
 			ChangeType:   syncbase.PutChange,
 			ValueBytes:   vomValue,
@@ -1205,7 +1205,7 @@
 			Continued:    true,
 		},
 		syncbase.WatchChange{
-			Table:        "tb",
+			Collection:   "c",
 			Row:          "b",
 			ChangeType:   syncbase.PutChange,
 			ValueBytes:   vomValue,
@@ -1218,10 +1218,10 @@
 	ctxBWithTimeout, cancelB := context.WithTimeout(clientBCtx, 10*time.Second)
 	defer cancelB()
 	// ClientA should see both changes as one batch.
-	wstream, _ := d.Watch(ctxAWithTimeout, "tb", "", initMarker)
+	wstream, _ := d.Watch(ctxAWithTimeout, "c", "", initMarker)
 	tu.CheckWatch(t, wstream, allChanges)
 	// ClientB should see only one change.
-	wstream, _ = d.Watch(ctxBWithTimeout, "tb", "", initMarker)
+	wstream, _ = d.Watch(ctxBWithTimeout, "c", "", initMarker)
 	tu.CheckWatch(t, wstream, allChanges[1:])
 }
 
@@ -1234,41 +1234,41 @@
 	clientCtx := tu.NewCtx(ctx, rootp, "client")
 	a := tu.CreateApp(t, adminCtx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, adminCtx, a, "d")
-	tb := tu.CreateTable(t, adminCtx, d, "tb")
+	c := tu.CreateCollection(t, adminCtx, d, "c")
 
 	// Set permissions. Lock client out of "b".
 	openAcl := tu.DefaultPerms("root:admin", "root:client")
 	adminAcl := tu.DefaultPerms("root:admin")
-	if err := tb.SetPermissions(adminCtx, openAcl); err != nil {
-		t.Fatalf("tb.SetPermissions() failed: %v", err)
+	if err := c.SetPermissions(adminCtx, openAcl); err != nil {
+		t.Fatalf("c.SetPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(adminCtx, syncbase.Prefix(""), openAcl); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(adminCtx, syncbase.Prefix(""), openAcl); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(adminCtx, syncbase.Prefix("b"), adminAcl); err != nil {
-		t.Fatalf("tb.SetPrefixPermissions() failed: %v", err)
+	if err := c.SetPrefixPermissions(adminCtx, syncbase.Prefix("b"), adminAcl); err != nil {
+		t.Fatalf("c.SetPrefixPermissions() failed: %v", err)
 	}
 
 	// Put "a/1" and "b/1" in a batch.
 	if err := syncbase.RunInBatch(adminCtx, d, wire.BatchOptions{}, func(b syncbase.BatchDatabase) error {
-		tb := b.Table("tb")
-		if err := tb.Put(adminCtx, "a/1", "value"); err != nil {
+		c := b.Collection("c")
+		if err := c.Put(adminCtx, "a/1", "value"); err != nil {
 			return err
 		}
-		return tb.Put(adminCtx, "b/1", "value")
+		return c.Put(adminCtx, "b/1", "value")
 	}); err != nil {
 		t.Fatalf("RunInBatch failed: %v", err)
 	}
 	// Put "c/1".
-	if err := tb.Put(adminCtx, "c/1", "value"); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(adminCtx, "c/1", "value"); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 
 	ctxWithTimeout, cancel := context.WithTimeout(clientCtx, 10*time.Second)
 	defer cancel()
 	// Start watches with empty resume marker.
-	wstreamAll, _ := d.Watch(ctxWithTimeout, "tb", "", nil)
-	wstreamD, _ := d.Watch(ctxWithTimeout, "tb", "d", nil)
+	wstreamAll, _ := d.Watch(ctxWithTimeout, "c", "", nil)
+	wstreamD, _ := d.Watch(ctxWithTimeout, "c", "d", nil)
 
 	resumeMarkerInitial, err := d.GetResumeMarker(clientCtx)
 	if err != nil {
@@ -1277,7 +1277,7 @@
 	vomValue, _ := vom.Encode("value")
 	initialChanges := []syncbase.WatchChange{
 		syncbase.WatchChange{
-			Table:        "tb",
+			Collection:   "c",
 			Row:          "a/1",
 			ChangeType:   syncbase.PutChange,
 			ValueBytes:   vomValue,
@@ -1285,7 +1285,7 @@
 			Continued:    true,
 		},
 		syncbase.WatchChange{
-			Table:        "tb",
+			Collection:   "c",
 			Row:          "c/1",
 			ChangeType:   syncbase.PutChange,
 			ValueBytes:   vomValue,
@@ -1299,11 +1299,11 @@
 	// More writes.
 	// Put "a/2" and "b/2" in a batch.
 	if err := syncbase.RunInBatch(adminCtx, d, wire.BatchOptions{}, func(b syncbase.BatchDatabase) error {
-		tb := b.Table("tb")
-		if err := tb.Put(adminCtx, "a/2", "value"); err != nil {
+		c := b.Collection("c")
+		if err := c.Put(adminCtx, "a/2", "value"); err != nil {
 			return err
 		}
-		return tb.Put(adminCtx, "b/2", "value")
+		return c.Put(adminCtx, "b/2", "value")
 	}); err != nil {
 		t.Fatalf("RunInBatch failed: %v", err)
 	}
@@ -1312,8 +1312,8 @@
 		t.Fatalf("d.GetResumeMarker() failed: %v", err)
 	}
 	// Put "d/1".
-	if err := tb.Put(adminCtx, "d/1", "value"); err != nil {
-		t.Fatalf("tb.Put() failed: %v", err)
+	if err := c.Put(adminCtx, "d/1", "value"); err != nil {
+		t.Fatalf("c.Put() failed: %v", err)
 	}
 	resumeMarkerAfterD1, err := d.GetResumeMarker(clientCtx)
 	if err != nil {
@@ -1322,14 +1322,14 @@
 
 	continuedChanges := []syncbase.WatchChange{
 		syncbase.WatchChange{
-			Table:        "tb",
+			Collection:   "c",
 			Row:          "a/2",
 			ChangeType:   syncbase.PutChange,
 			ValueBytes:   vomValue,
 			ResumeMarker: resumeMarkerAfterA2B2,
 		},
 		syncbase.WatchChange{
-			Table:        "tb",
+			Collection:   "c",
 			Row:          "d/1",
 			ChangeType:   syncbase.PutChange,
 			ValueBytes:   vomValue,
@@ -1351,7 +1351,7 @@
 	defer cleanup()
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	d := tu.CreateDatabase(t, ctx, a, "d")
-	tb := tu.CreateTable(t, ctx, d, "tb")
+	c := tu.CreateCollection(t, ctx, d, "c")
 
 	resumeMarker, err := d.GetResumeMarker(ctx)
 	if err != nil {
@@ -1359,11 +1359,11 @@
 	}
 	ctxWithTimeout, cancel := context.WithTimeout(ctx, 10*time.Second)
 	defer cancel()
-	wstream, _ := d.Watch(ctxWithTimeout, "tb", "a", resumeMarker)
+	wstream, _ := d.Watch(ctxWithTimeout, "c", "a", resumeMarker)
 	vomValue, _ := vom.Encode("value")
 	for i := 0; i < 10; i++ {
 		// Put "abc".
-		r := tb.Row("abc")
+		r := c.Row("abc")
 		if err := r.Put(ctx, "value"); err != nil {
 			t.Fatalf("r.Put() failed: %v", err)
 		}
@@ -1374,7 +1374,7 @@
 			t.Fatalf("wstream.Advance() reached the end: %v", wstream.Err())
 		}
 		want := syncbase.WatchChange{
-			Table:        "tb",
+			Collection:   "c",
 			Row:          "abc",
 			ChangeType:   syncbase.PutChange,
 			ValueBytes:   vomValue,
@@ -1399,7 +1399,7 @@
 		t.Fatalf("d.GetResumeMarker() failed: %v", err)
 	}
 	ctxCancel, cancel := context.WithCancel(ctx)
-	wstream, err := d.Watch(ctxCancel, "tb", "a", resumeMarker)
+	wstream, err := d.Watch(ctxCancel, "c", "a", resumeMarker)
 	if err != nil {
 		t.Fatalf("d.Watch() failed: %v", err)
 	}
diff --git a/syncbase/collection.go b/syncbase/collection.go
new file mode 100644
index 0000000..e57ee05
--- /dev/null
+++ b/syncbase/collection.go
@@ -0,0 +1,126 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syncbase
+
+import (
+	"v.io/v23/context"
+	"v.io/v23/naming"
+	"v.io/v23/security/access"
+	wire "v.io/v23/services/syncbase"
+	"v.io/v23/syncbase/util"
+)
+
+func newCollection(parentFullName, relativeName string, schemaVersion int32) Collection {
+	// Escape relativeName so that any forward slashes get dropped, thus ensuring
+	// that the server will interpret fullName as referring to a collection
+	// object. Note that the server will still reject this name if
+	// util.ValidCollectionName returns false.
+	fullName := naming.Join(parentFullName, util.Escape(relativeName))
+	return &collection{
+		c:               wire.CollectionClient(fullName),
+		fullName:        fullName,
+		name:            relativeName,
+		dbSchemaVersion: schemaVersion,
+	}
+}
+
+type collection struct {
+	c               wire.CollectionClientMethods
+	fullName        string
+	name            string
+	dbSchemaVersion int32
+}
+
+var _ Collection = (*collection)(nil)
+
+// Name implements Collection.Name.
+func (c *collection) Name() string {
+	return c.name
+}
+
+// FullName implements Collection.FullName.
+func (c *collection) FullName() string {
+	return c.fullName
+}
+
+// Exists implements Collection.Exists.
+func (c *collection) Exists(ctx *context.T) (bool, error) {
+	return c.c.Exists(ctx, c.dbSchemaVersion)
+}
+
+// Create implements Collection.Create.
+func (c *collection) Create(ctx *context.T, perms access.Permissions) error {
+	return c.c.Create(ctx, c.dbSchemaVersion, perms)
+}
+
+// Destroy implements Collection.Destroy.
+func (c *collection) Destroy(ctx *context.T) error {
+	return c.c.Destroy(ctx, c.dbSchemaVersion)
+}
+
+// GetPermissions implements Collection.GetPermissions.
+func (c *collection) GetPermissions(ctx *context.T) (access.Permissions, error) {
+	return c.c.GetPermissions(ctx, c.dbSchemaVersion)
+}
+
+// SetPermissions implements Collection.SetPermissions.
+func (c *collection) SetPermissions(ctx *context.T, perms access.Permissions) error {
+	return c.c.SetPermissions(ctx, c.dbSchemaVersion, perms)
+}
+
+// Row implements Collection.Row.
+func (c *collection) Row(key string) Row {
+	return newRow(c.fullName, key, c.dbSchemaVersion)
+}
+
+// Get implements Collection.Get.
+func (c *collection) Get(ctx *context.T, key string, value interface{}) error {
+	return c.Row(key).Get(ctx, value)
+}
+
+// Put implements Collection.Put.
+func (c *collection) Put(ctx *context.T, key string, value interface{}) error {
+	return c.Row(key).Put(ctx, value)
+}
+
+// Delete implements Collection.Delete.
+func (c *collection) Delete(ctx *context.T, key string) error {
+	return c.Row(key).Delete(ctx)
+}
+
+// DeleteRange implements Collection.DeleteRange.
+func (c *collection) DeleteRange(ctx *context.T, r RowRange) error {
+	return c.c.DeleteRange(ctx, c.dbSchemaVersion, []byte(r.Start()), []byte(r.Limit()))
+}
+
+// Scan implements Collection.Scan.
+func (c *collection) Scan(ctx *context.T, r RowRange) ScanStream {
+	ctx, cancel := context.WithCancel(ctx)
+	call, err := c.c.Scan(ctx, c.dbSchemaVersion, []byte(r.Start()), []byte(r.Limit()))
+	if err != nil {
+		return &InvalidScanStream{Error: err}
+	}
+	return newScanStream(cancel, call)
+}
+
+// GetPrefixPermissions implements Collection.GetPrefixPermissions.
+func (c *collection) GetPrefixPermissions(ctx *context.T, key string) ([]PrefixPermissions, error) {
+	wirePermsList, err := c.c.GetPrefixPermissions(ctx, c.dbSchemaVersion, key)
+	permsList := []PrefixPermissions{}
+	for _, v := range wirePermsList {
+		permsList = append(permsList, PrefixPermissions{Prefix: Prefix(v.Prefix), Perms: v.Perms})
+	}
+	return permsList, err
+}
+
+// SetPrefixPermissions implements Collection.SetPrefixPermissions.
+func (c *collection) SetPrefixPermissions(ctx *context.T, prefix PrefixRange, perms access.Permissions) error {
+	return c.c.SetPrefixPermissions(ctx, c.dbSchemaVersion, prefix.Prefix(), perms)
+}
+
+// DeletePrefixPermissions implements Collection.DeletePrefixPermissions.
+func (c *collection) DeletePrefixPermissions(ctx *context.T, prefix PrefixRange) error {
+	return c.c.DeletePrefixPermissions(ctx, c.dbSchemaVersion, prefix.Prefix())
+}
diff --git a/syncbase/database.go b/syncbase/database.go
index b57cb27..e6829a2 100644
--- a/syncbase/database.go
+++ b/syncbase/database.go
@@ -100,16 +100,16 @@
 	return d.c.Exists(ctx, d.schemaVersion())
 }
 
-// Table implements Database.Table.
-func (d *database) Table(relativeName string) Table {
-	return newTable(d.fullName, relativeName, d.schemaVersion())
+// Collection implements Database.Collection.
+func (d *database) Collection(relativeName string) Collection {
+	return newCollection(d.fullName, relativeName, d.schemaVersion())
 }
 
-// ListTables implements Database.ListTables.
-func (d *database) ListTables(ctx *context.T) ([]string, error) {
+// ListCollections implements Database.ListCollections.
+func (d *database) ListCollections(ctx *context.T) ([]string, error) {
 	// See comment in v.io/v23/services/syncbase/service.vdl for why we
-	// can't implement ListTables using Glob (via util.ListChildren).
-	return d.c.ListTables(ctx)
+	// can't implement ListCollections using Glob (via util.ListChildren).
+	return d.c.ListCollections(ctx)
 }
 
 // Create implements Database.Create.
@@ -183,13 +183,13 @@
 }
 
 // Watch implements the Database interface.
-func (d *database) Watch(ctx *context.T, table, prefix string, resumeMarker watch.ResumeMarker) (WatchStream, error) {
-	if !util.ValidTableName(table) {
-		return nil, verror.New(svcwire.ErrInvalidName, ctx, table)
+func (d *database) Watch(ctx *context.T, collection, prefix string, resumeMarker watch.ResumeMarker) (WatchStream, error) {
+	if !util.ValidCollectionName(collection) {
+		return nil, verror.New(svcwire.ErrInvalidName, ctx, collection)
 	}
 	ctx, cancel := context.WithCancel(ctx)
 	call, err := d.c.WatchGlob(ctx, watch.GlobRequest{
-		Pattern:      naming.Join(table, prefix+"*"),
+		Pattern:      naming.Join(collection, prefix+"*"),
 		ResumeMarker: resumeMarker,
 	})
 	if err != nil {
diff --git a/syncbase/exec_test.go b/syncbase/exec_test.go
index d0b1619..71c3670 100644
--- a/syncbase/exec_test.go
+++ b/syncbase/exec_test.go
@@ -51,25 +51,25 @@
 var t2015_07_01 time.Time
 var t2015_07_01_01_23_45 time.Time
 
-var customerTable syncbase.Table
-var numbersTable syncbase.Table
-var fooTable syncbase.Table
-var keyIndexDataTable syncbase.Table
-var bigTable syncbase.Table
+var customerCollection syncbase.Collection
+var numbersCollection syncbase.Collection
+var fooCollection syncbase.Collection
+var keyIndexDataCollection syncbase.Collection
+var bigCollection syncbase.Collection
 
 func setup(t *testing.T) {
 	var sName string
 	ctx, sName, cleanup = tu.SetupOrDie(nil)
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	db = tu.CreateDatabase(t, ctx, a, "db")
-	customerTable = tu.CreateTable(t, ctx, db, "Customer")
-	numbersTable = tu.CreateTable(t, ctx, db, "Numbers")
-	fooTable = tu.CreateTable(t, ctx, db, "Foo")
-	keyIndexDataTable = tu.CreateTable(t, ctx, db, "KeyIndexData")
-	bigTable = tu.CreateTable(t, ctx, db, "BigTable")
+	customerCollection = tu.CreateCollection(t, ctx, db, "Customer")
+	numbersCollection = tu.CreateCollection(t, ctx, db, "Numbers")
+	fooCollection = tu.CreateCollection(t, ctx, db, "Foo")
+	keyIndexDataCollection = tu.CreateCollection(t, ctx, db, "KeyIndexData")
+	bigCollection = tu.CreateCollection(t, ctx, db, "BigCollection")
 }
 
-func initTables(t *testing.T) {
+func initCollections(t *testing.T) {
 	t20150122131101, _ := time.Parse("Jan 2 2006 15:04:05 -0700 MST", "Jan 22 2015 13:11:01 -0800 PST")
 	t20150210161202, _ := time.Parse("Jan 2 2006 15:04:05 -0700 MST", "Feb 10 2015 16:12:02 -0800 PST")
 	t20150311101303, _ := time.Parse("Jan 2 2006 15:04:05 -0700 MST", "Mar 11 2015 10:13:03 -0700 PDT")
@@ -94,106 +94,106 @@
 	k := "001"
 	c := testdata.Customer{"John Smith", 1, true, testdata.AddressInfo{"1 Main St.", "Palo Alto", "CA", "94303"}, testdata.CreditReport{Agency: testdata.CreditAgencyEquifax, Report: testdata.AgencyReportEquifaxReport{testdata.EquifaxCreditReport{'A'}}}}
 	customerEntries = append(customerEntries, kv{k, vdl.ValueOf(c)})
-	if err := customerTable.Put(ctx, k, c); err != nil {
-		t.Fatalf("customerTable.Put() failed: %v", err)
+	if err := customerCollection.Put(ctx, k, c); err != nil {
+		t.Fatalf("customerCollection.Put() failed: %v", err)
 	}
 
 	k = "001001"
 	i := testdata.Invoice{1, 1000, t20150122131101, 42, testdata.AddressInfo{"1 Main St.", "Palo Alto", "CA", "94303"}}
 	customerEntries = append(customerEntries, kv{k, vdl.ValueOf(i)})
-	if err := customerTable.Put(ctx, k, i); err != nil {
-		t.Fatalf("customerTable.Put() failed: %v", err)
+	if err := customerCollection.Put(ctx, k, i); err != nil {
+		t.Fatalf("customerCollection.Put() failed: %v", err)
 	}
 
 	k = "001002"
 	i = testdata.Invoice{1, 1003, t20150210161202, 7, testdata.AddressInfo{"2 Main St.", "Palo Alto", "CA", "94303"}}
 	customerEntries = append(customerEntries, kv{k, vdl.ValueOf(i)})
-	if err := customerTable.Put(ctx, k, i); err != nil {
-		t.Fatalf("customerTable.Put() failed: %v", err)
+	if err := customerCollection.Put(ctx, k, i); err != nil {
+		t.Fatalf("customerCollection.Put() failed: %v", err)
 	}
 
 	k = "001003"
 	i = testdata.Invoice{1, 1005, t20150311101303, 88, testdata.AddressInfo{"3 Main St.", "Palo Alto", "CA", "94303"}}
 	customerEntries = append(customerEntries, kv{k, vdl.ValueOf(i)})
-	if err := customerTable.Put(ctx, k, i); err != nil {
-		t.Fatalf("customerTable.Put() failed: %v", err)
+	if err := customerCollection.Put(ctx, k, i); err != nil {
+		t.Fatalf("customerCollection.Put() failed: %v", err)
 	}
 
 	k = "002"
 	c = testdata.Customer{"Bat Masterson", 2, true, testdata.AddressInfo{"777 Any St.", "Collins", "IA", "50055"}, testdata.CreditReport{Agency: testdata.CreditAgencyTransUnion, Report: testdata.AgencyReportTransUnionReport{testdata.TransUnionCreditReport{80}}}}
 	customerEntries = append(customerEntries, kv{k, vdl.ValueOf(c)})
-	if err := customerTable.Put(ctx, k, c); err != nil {
-		t.Fatalf("customerTable.Put() failed: %v", err)
+	if err := customerCollection.Put(ctx, k, c); err != nil {
+		t.Fatalf("customerCollection.Put() failed: %v", err)
 	}
 
 	k = "002001"
 	i = testdata.Invoice{2, 1001, t20150317111404, 166, testdata.AddressInfo{"777 Any St.", "collins", "IA", "50055"}}
 	customerEntries = append(customerEntries, kv{k, vdl.ValueOf(i)})
-	if err := customerTable.Put(ctx, k, i); err != nil {
-		t.Fatalf("customerTable.Put() failed: %v", err)
+	if err := customerCollection.Put(ctx, k, i); err != nil {
+		t.Fatalf("customerCollection.Put() failed: %v", err)
 	}
 
 	k = "002002"
 	i = testdata.Invoice{2, 1002, t20150317131505, 243, testdata.AddressInfo{"888 Any St.", "collins", "IA", "50055"}}
 	customerEntries = append(customerEntries, kv{k, vdl.ValueOf(i)})
-	if err := customerTable.Put(ctx, k, i); err != nil {
-		t.Fatalf("customerTable.Put() failed: %v", err)
+	if err := customerCollection.Put(ctx, k, i); err != nil {
+		t.Fatalf("customerCollection.Put() failed: %v", err)
 	}
 
 	k = "002003"
 	i = testdata.Invoice{2, 1004, t20150412221606, 787, testdata.AddressInfo{"999 Any St.", "collins", "IA", "50055"}}
 	customerEntries = append(customerEntries, kv{k, vdl.ValueOf(i)})
-	if err := customerTable.Put(ctx, k, i); err != nil {
-		t.Fatalf("customerTable.Put() failed: %v", err)
+	if err := customerCollection.Put(ctx, k, i); err != nil {
+		t.Fatalf("customerCollection.Put() failed: %v", err)
 	}
 
 	k = "002004"
 	i = testdata.Invoice{2, 1006, t20150413141707, 88, testdata.AddressInfo{"101010 Any St.", "collins", "IA", "50055"}}
 	customerEntries = append(customerEntries, kv{k, vdl.ValueOf(i)})
-	if err := customerTable.Put(ctx, k, i); err != nil {
-		t.Fatalf("customerTable.Put() failed: %v", err)
+	if err := customerCollection.Put(ctx, k, i); err != nil {
+		t.Fatalf("customerCollection.Put() failed: %v", err)
 	}
 
 	k = "003"
 	c = testdata.Customer{"John \"JOS\" O'Steed", 3, true, testdata.AddressInfo{"100 Queen St.", "New London", "CT", "06320"}, testdata.CreditReport{Agency: testdata.CreditAgencyExperian, Report: testdata.AgencyReportExperianReport{testdata.ExperianCreditReport{testdata.ExperianRatingGood}}}}
 	customerEntries = append(customerEntries, kv{k, vdl.ValueOf(c)})
-	if err := customerTable.Put(ctx, k, c); err != nil {
-		t.Fatalf("customerTable.Put() failed: %v", err)
+	if err := customerCollection.Put(ctx, k, c); err != nil {
+		t.Fatalf("customerCollection.Put() failed: %v", err)
 	}
 
 	k = "001"
 	n := testdata.Numbers{byte(12), uint16(1234), uint32(5678), uint64(999888777666), int16(9876), int32(876543), int64(128), float32(3.14159), float64(2.71828182846)}
 	numbersEntries = append(numbersEntries, kv{k, vdl.ValueOf(n)})
-	if err := numbersTable.Put(ctx, k, n); err != nil {
-		t.Fatalf("numbersTable.Put() failed: %v", err)
+	if err := numbersCollection.Put(ctx, k, n); err != nil {
+		t.Fatalf("numbersCollection.Put() failed: %v", err)
 	}
 
 	k = "002"
 	n = testdata.Numbers{byte(9), uint16(99), uint32(999), uint64(9999999), int16(9), int32(99), int64(88), float32(1.41421356237), float64(1.73205080757)}
 	numbersEntries = append(numbersEntries, kv{k, vdl.ValueOf(n)})
-	if err := numbersTable.Put(ctx, k, n); err != nil {
-		t.Fatalf("numbersTable.Put() failed: %v", err)
+	if err := numbersCollection.Put(ctx, k, n); err != nil {
+		t.Fatalf("numbersCollection.Put() failed: %v", err)
 	}
 
 	k = "003"
 	n = testdata.Numbers{byte(210), uint16(210), uint32(210), uint64(210), int16(210), int32(210), int64(210), float32(210.0), float64(210.0)}
 	numbersEntries = append(numbersEntries, kv{k, vdl.ValueOf(n)})
-	if err := numbersTable.Put(ctx, k, n); err != nil {
-		t.Fatalf("numbersTable.Put() failed: %v", err)
+	if err := numbersCollection.Put(ctx, k, n); err != nil {
+		t.Fatalf("numbersCollection.Put() failed: %v", err)
 	}
 
 	k = "001"
 	f := testdata.FooType{testdata.BarType{testdata.BazType{"FooBarBaz", testdata.TitleOrValueTypeTitle{"Vice President"}}}}
 	fooEntries = append(fooEntries, kv{k, vdl.ValueOf(f)})
-	if err := fooTable.Put(ctx, k, f); err != nil {
-		t.Fatalf("fooTable.Put() failed: %v", err)
+	if err := fooCollection.Put(ctx, k, f); err != nil {
+		t.Fatalf("fooCollection.Put() failed: %v", err)
 	}
 
 	k = "002"
 	f = testdata.FooType{testdata.BarType{testdata.BazType{"BazBarFoo", testdata.TitleOrValueTypeValue{42}}}}
 	fooEntries = append(fooEntries, kv{k, vdl.ValueOf(f)})
-	if err := fooTable.Put(ctx, k, f); err != nil {
-		t.Fatalf("fooTable.Put() failed: %v", err)
+	if err := fooCollection.Put(ctx, k, f); err != nil {
+		t.Fatalf("fooCollection.Put() failed: %v", err)
 	}
 
 	k = "aaa"
@@ -204,15 +204,15 @@
 		map[string]struct{}{"I’ll grind his bones to mix my bread": {}},
 	}
 	keyIndexDataEntries = append(keyIndexDataEntries, kv{k, vdl.ValueOf(kid)})
-	if err := keyIndexDataTable.Put(ctx, k, kid); err != nil {
-		t.Fatalf("keyIndexDataTable.Put() failed: %v", err)
+	if err := keyIndexDataCollection.Put(ctx, k, kid); err != nil {
+		t.Fatalf("keyIndexDataCollection.Put() failed: %v", err)
 	}
 
 	for i := 100; i < 301; i++ {
 		k = fmt.Sprintf("%d", i)
 		b := testdata.BigData{k}
-		if err := bigTable.Put(ctx, k, b); err != nil {
-			t.Fatalf("bigTable.Put() failed: %v", err)
+		if err := bigCollection.Put(ctx, k, b); err != nil {
+			t.Fatalf("bigCollection.Put() failed: %v", err)
 		}
 	}
 }
@@ -268,7 +268,7 @@
 func TestExecSelect(t *testing.T) {
 	setup(t)
 	defer cleanup()
-	initTables(t)
+	initCollections(t)
 	basic := []execSelectTest{
 		{
 			// Select values for all customer records.
@@ -981,12 +981,12 @@
 			}},
 		},
 		{
-			"select k, v.Key from BigTable where k < \"101\" or k = \"200\" or k like \"300%\"",
+			"select k, v.Key from BigCollection where k < \"101\" or k = \"200\" or k like \"300%\"",
 			[]string{"k", "v.Key"},
 			[][]*vdl.Value{svPair("100"), svPair("200"), svPair("300")},
 		},
 		{
-			"select k, v.Key from BigTable where k like \"10_\" or k like \"20_\"",
+			"select k, v.Key from BigCollection where k like \"10_\" or k like \"20_\"",
 			[]string{"k", "v.Key"},
 			[][]*vdl.Value{
 				svPair("100"),
@@ -1012,7 +1012,7 @@
 			},
 		},
 		{
-			"select k, v.Key from BigTable where k like \"_%9\"",
+			"select k, v.Key from BigCollection where k like \"_%9\"",
 			[]string{"k", "v.Key"},
 			[][]*vdl.Value{
 				svPair("109"),
@@ -1038,7 +1038,7 @@
 			},
 		},
 		{
-			"select k, v.Key from BigTable where k like \"__0\"",
+			"select k, v.Key from BigCollection where k like \"__0\"",
 			[]string{"k", "v.Key"},
 			[][]*vdl.Value{
 				svPair("100"),
@@ -1065,7 +1065,7 @@
 			},
 		},
 		{
-			"select k, v.Key from BigTable where k like \"10%\" or  k like \"20%\" or  k like \"30%\"",
+			"select k, v.Key from BigCollection where k like \"10%\" or  k like \"20%\" or  k like \"30%\"",
 			[]string{"k", "v.Key"},
 			[][]*vdl.Value{
 				svPair("100"),
@@ -1092,12 +1092,12 @@
 			},
 		},
 		{
-			"select k, v.Key from BigTable where k like \"1__\" and  k like \"_2_\" and  k like \"__3\"",
+			"select k, v.Key from BigCollection where k like \"1__\" and  k like \"_2_\" and  k like \"__3\"",
 			[]string{"k", "v.Key"},
 			[][]*vdl.Value{svPair("123")},
 		},
 		{
-			"select k, v.Key from BigTable where (k >  \"100\" and k < \"103\") or (k > \"205\" and k < \"208\")",
+			"select k, v.Key from BigCollection where (k >  \"100\" and k < \"103\") or (k > \"205\" and k < \"208\")",
 			[]string{"k", "v.Key"},
 			[][]*vdl.Value{
 				svPair("101"),
@@ -1107,7 +1107,7 @@
 			},
 		},
 		{
-			"select k, v.Key from BigTable where k <=  \"100\" or k = \"101\" or k >= \"300\" or (k <> \"299\" and k not like \"300\" and k >= \"298\")",
+			"select k, v.Key from BigCollection where k <=  \"100\" or k = \"101\" or k >= \"300\" or (k <> \"299\" and k not like \"300\" and k >= \"298\")",
 			[]string{"k", "v.Key"},
 			[][]*vdl.Value{
 				svPair("100"),
@@ -1117,7 +1117,7 @@
 			},
 		},
 		{
-			"select k, v.Key from BigTable where k like  \"1%\" and k like \"%9\"",
+			"select k, v.Key from BigCollection where k like  \"1%\" and k like \"%9\"",
 			[]string{"k", "v.Key"},
 			[][]*vdl.Value{
 				svPair("109"),
@@ -1133,7 +1133,7 @@
 			},
 		},
 		{
-			"select k, v.Key from BigTable where k like  \"3%\" and k like \"30%\" and k like \"300%\"",
+			"select k, v.Key from BigCollection where k like  \"3%\" and k like \"30%\" and k like \"300%\"",
 			[]string{"k", "v.Key"},
 			[][]*vdl.Value{svPair("300")},
 		},
@@ -1162,7 +1162,7 @@
 func TestExecDelete(t *testing.T) {
 	basic := []execDeleteTest{
 		{
-			// Delete all k/v pairs in the customer table.
+			// Delete all k/v pairs in the customer collection.
 			"delete from Customer",
 			[]string{"Count"},
 			[][]*vdl.Value{
@@ -1568,7 +1568,7 @@
 	setup(t)
 	defer cleanup()
 	for _, test := range basic {
-		initTables(t)
+		initCollections(t)
 		headers, rs, err := db.Exec(ctx, test.delQuery)
 		if err != nil {
 			t.Errorf("delQuery: %s; got %v, want nil", test.delQuery, err)
@@ -1607,7 +1607,7 @@
 func TestQuerySelectClause(t *testing.T) {
 	setup(t)
 	defer cleanup()
-	initTables(t)
+	initCollections(t)
 	basic := []execSelectTest{
 		{
 			// Select numeric types
@@ -1790,7 +1790,7 @@
 func TestQueryWhereClause(t *testing.T) {
 	setup(t)
 	defer cleanup()
-	initTables(t)
+	initCollections(t)
 	basic := []execSelectTest{
 		{
 			// Select on numeric comparisons with equals
@@ -2104,7 +2104,7 @@
 func TestQueryEscapeClause(t *testing.T) {
 	setup(t)
 	defer cleanup()
-	initTables(t)
+	initCollections(t)
 	basic := []execSelectTest{
 		{
 			"select k from Customer where \"abc%\" like \"abc^%\" escape '^'",
@@ -2195,7 +2195,7 @@
 func TestQueryLimitAndOffsetClauses(t *testing.T) {
 	setup(t)
 	defer cleanup()
-	initTables(t)
+	initCollections(t)
 	basic := []execSelectTest{
 		{
 			"select k from Customer limit 2 offset 3",
@@ -2258,7 +2258,7 @@
 func TestPreExecFunctions(t *testing.T) {
 	setup(t)
 	defer cleanup()
-	initTables(t)
+	initCollections(t)
 	basic := []preExecFunctionTest{
 		{
 			"select Now() from Customer",
@@ -2294,7 +2294,7 @@
 func TestExecErrors(t *testing.T) {
 	setup(t)
 	defer cleanup()
-	initTables(t)
+	initCollections(t)
 	basic := []execSelectErrorTest{
 		{
 			"select a from Customer",
@@ -2344,7 +2344,7 @@
 func TestQueryErrors(t *testing.T) {
 	setup(t)
 	defer cleanup()
-	initTables(t)
+	initCollections(t)
 	basic := []execSelectErrorTest{
 		// Produce every error in the book (make that, every one that is possible to produce).
 		{
@@ -2471,7 +2471,7 @@
 		},
 		// *OffsetMustBeGe0 cannot be produced because the parser won't produce
 		// an offset < 0.
-		// *ScanError Cannot produce a [table].ScanError.
+		// *ScanError Cannot produce a [collection].ScanError.
 		{
 			"select k from Blah",
 			// TODO(sadovsky): Error messages should never contain storage engine
@@ -2532,7 +2532,7 @@
 func TestQueryErrorsPlatformDependentText(t *testing.T) {
 	setup(t)
 	defer cleanup()
-	initTables(t)
+	initCollections(t)
 	basic := []execSelectErrorTest{
 		// These errors contain installation dependent parts to the error.  The test is
 		// more relaxed (it doesn't check the suffix) in order to account for this.
@@ -2560,7 +2560,7 @@
 func TestQueryStatementSizeExceeded(t *testing.T) {
 	setup(t)
 	defer cleanup()
-	initTables(t)
+	initCollections(t)
 	q := fmt.Sprintf("select a from b where c = \"%s\"", strings.Repeat("x", 12000))
 
 	_, rs, err := db.Exec(ctx, q)
@@ -2580,7 +2580,7 @@
 func TestExecParamSelect(t *testing.T) {
 	setup(t)
 	defer cleanup()
-	initTables(t)
+	initCollections(t)
 	t20120317, _ := time.Parse("2006-01-02 MST", "2012-03-17 PDT")
 	basic := []execSelectParamTest{
 		{
@@ -2747,7 +2747,7 @@
 			},
 		},*/
 		{
-			"select k, v.Key from BigTable where k like StrCat(?, \"_\") or k like StrCat(?, \"_\")",
+			"select k, v.Key from BigCollection where k like StrCat(?, \"_\") or k like StrCat(?, \"_\")",
 			[]interface{}{
 				"10",
 				"20",
@@ -2777,7 +2777,7 @@
 			},
 		},
 		{
-			"select k, v.Key from BigTable where k <= ? or k = ? or k >= ? or (k <> ? and k not like ? and k >= ?)",
+			"select k, v.Key from BigCollection where k <= ? or k = ? or k >= ? or (k <> ? and k not like ? and k >= ?)",
 			[]interface{}{
 				"100",
 				"101",
@@ -2926,7 +2926,7 @@
 	setup(t)
 	defer cleanup()
 	for _, test := range basic {
-		initTables(t)
+		initCollections(t)
 		headers, rs, err := db.Exec(ctx, test.delQuery, test.delParams...)
 		if err != nil {
 			t.Errorf("delQuery: %s, delParams: %v; got %v, want nil", test.delQuery, test.delParams, err)
@@ -2965,7 +2965,7 @@
 func TestExecParamErrors(t *testing.T) {
 	setup(t)
 	defer cleanup()
-	initTables(t)
+	initCollections(t)
 	basic := []execSelectParamErrorTest{
 		// Produce parameter related errors.
 		{
diff --git a/syncbase/featuretests/blob_v23_test.go b/syncbase/featuretests/blob_v23_test.go
index 33cc334..ea6d8de 100644
--- a/syncbase/featuretests/blob_v23_test.go
+++ b/syncbase/featuretests/blob_v23_test.go
@@ -31,7 +31,7 @@
 	sgName := naming.Join("s0", common.SyncbaseSuffix, "SG1")
 
 	ok(t, populateData(sbs[0].clientCtx, "s0", "foo", 0, 10))
-	ok(t, createSyncgroup(sbs[0].clientCtx, "s0", sgName, "tb:foo", "", sbBlessings(sbs), nil))
+	ok(t, createSyncgroup(sbs[0].clientCtx, "s0", sgName, "c:foo", "", sbBlessings(sbs), nil))
 	ok(t, joinSyncgroup(sbs[1].clientCtx, "s1", sgName))
 	ok(t, verifySyncgroupData(sbs[1].clientCtx, "s1", "foo", 0, 10))
 
@@ -68,7 +68,7 @@
 func generateBlob(ctx *context.T, syncbaseName, keyPrefix string, pos int, data []byte) error {
 	a := syncbase.NewService(syncbaseName).App(testApp)
 	d := a.Database(testDb, nil)
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	b, err := d.CreateBlob(ctx)
 	if err != nil {
@@ -93,7 +93,7 @@
 
 	// Put the BlobRef in a key.
 	key := fmt.Sprintf("%s%d", keyPrefix, pos)
-	r := tb.Row(key)
+	r := c.Row(key)
 	s := testStruct{Val: "testkey" + key, Blob: b.Ref()}
 	if err := r.Put(ctx, s); err != nil {
 		return fmt.Errorf("r.Put() failed: %v", err)
@@ -105,10 +105,10 @@
 func fetchBlob(ctx *context.T, syncbaseName, keyPrefix string, pos int, wantSize int64, skipIncStatus bool) error {
 	a := syncbase.NewService(syncbaseName).App(testApp)
 	d := a.Database(testDb, nil)
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	key := fmt.Sprintf("%s%d", keyPrefix, pos)
-	r := tb.Row(key)
+	r := c.Row(key)
 	var s testStruct
 
 	// Try for 10 seconds to get the new value.
@@ -174,10 +174,10 @@
 func getBlob(ctx *context.T, syncbaseName, keyPrefix string, pos int, wantVal []byte, offset int64) error {
 	a := syncbase.NewService(syncbaseName).App(testApp)
 	d := a.Database(testDb, nil)
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	key := fmt.Sprintf("%s%d", keyPrefix, pos)
-	r := tb.Row(key)
+	r := c.Row(key)
 	var s testStruct
 
 	// Try for 10 seconds to get the new value.
@@ -217,7 +217,7 @@
 func generateBigBlob(ctx *context.T, syncbaseName, keyPrefix string, pos int) error {
 	a := syncbase.NewService(syncbaseName).App(testApp)
 	d := a.Database(testDb, nil)
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	b, err := d.CreateBlob(ctx)
 	if err != nil {
@@ -253,7 +253,7 @@
 
 	// Put the BlobRef in a key.
 	key := fmt.Sprintf("%s%d", keyPrefix, pos)
-	r := tb.Row(key)
+	r := c.Row(key)
 
 	// Blob hash is transferred via structured store.
 	s := testStruct{Val: hashToString(hasher.Sum(nil)), Blob: b.Ref()}
@@ -268,10 +268,10 @@
 func getBigBlob(ctx *context.T, syncbaseName, keyPrefix string, pos int) error {
 	a := syncbase.NewService(syncbaseName).App(testApp)
 	d := a.Database(testDb, nil)
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	key := fmt.Sprintf("%s%d", keyPrefix, pos)
-	r := tb.Row(key)
+	r := c.Row(key)
 	var s testStruct
 
 	// Try for 10 seconds to get the new value.
diff --git a/syncbase/featuretests/client_v23_test.go b/syncbase/featuretests/client_v23_test.go
index 48ca568..d8df389 100644
--- a/syncbase/featuretests/client_v23_test.go
+++ b/syncbase/featuretests/client_v23_test.go
@@ -27,7 +27,7 @@
 	// See https://github.com/vanadium/issues/issues/1110
 	sh.StartSyncbase(serverCreds, syncbaselib.Opts{Name: testSbName}, `{"Resolve": {"In":["root:server", "root:client"]}, "Read": {"In":["root:server", "root:client"]}, "Write": {"In":["root:server", "root:client"]}}`)
 
-	// Create app, database and table.
+	// Create app, database and collection.
 	// TODO(ivanpi): Use setupAppA.
 	ctx := sh.ForkContext("client")
 	a := syncbase.NewService(testSbName).App("a")
@@ -38,9 +38,9 @@
 	if err := d.Create(ctx, nil); err != nil {
 		t.Fatalf("unable to create a database: %v", err)
 	}
-	tb := d.Table("tb")
-	if err := tb.Create(ctx, nil); err != nil {
-		t.Fatalf("unable to create a table: %v", err)
+	c := d.Collection("c")
+	if err := c.Create(ctx, nil); err != nil {
+		t.Fatalf("unable to create a collection: %v", err)
 	}
 	marker, err := d.GetResumeMarker(ctx)
 	if err != nil {
@@ -48,7 +48,7 @@
 	}
 
 	// Do a Put followed by a Get.
-	r := tb.Row("testkey")
+	r := c.Row("testkey")
 	if err := r.Put(ctx, "testvalue"); err != nil {
 		t.Fatalf("r.Put() failed: %v", err)
 	}
@@ -63,7 +63,7 @@
 	// Do a watch from the resume marker before the put operation.
 	ctxWithTimeout, cancel := context.WithTimeout(ctx, 10*time.Second)
 	defer cancel()
-	stream, err := d.Watch(ctxWithTimeout, "tb", "", marker)
+	stream, err := d.Watch(ctxWithTimeout, "c", "", marker)
 	if err != nil {
 		t.Fatalf("unable to start a watch %v", err)
 	}
@@ -71,8 +71,8 @@
 		t.Fatalf("watch stream unexpectedly reached the end: %v", stream.Err())
 	}
 	change := stream.Change()
-	if got, want := change.Table, "tb"; got != want {
-		t.Fatalf("unexpected watch table: got %q, want %q", got, want)
+	if got, want := change.Collection, "c"; got != want {
+		t.Fatalf("unexpected watch collection: got %q, want %q", got, want)
 	}
 	if got, want := change.Row, "testkey"; got != want {
 		t.Fatalf("unexpected watch row: got %q, want %q", got, want)
diff --git a/syncbase/featuretests/cr_v23_test.go b/syncbase/featuretests/cr_v23_test.go
index ab793ff..d97e6e1 100644
--- a/syncbase/featuretests/cr_v23_test.go
+++ b/syncbase/featuretests/cr_v23_test.go
@@ -326,7 +326,7 @@
 	sgName = naming.Join("s0", common.SyncbaseSuffix, "SG1")
 
 	// Create syncgroup and populate data on s0.
-	ok(t, createSyncgroup(sbs[0].clientCtx, "s0", sgName, "tb:foo", "", sbBlessings(sbs), nil))
+	ok(t, createSyncgroup(sbs[0].clientCtx, "s0", sgName, "c:foo", "", sbBlessings(sbs), nil))
 	ok(t, populateData(sbs[0].clientCtx, "s0", "foo", 0, numInitRows))
 
 	// Join syncgroup and verify data on s1.
@@ -428,11 +428,11 @@
 	a := syncbase.NewService(syncbaseName).App("a")
 	d := a.Database("d", makeSchema(schemaPrefix, &CRImpl{syncbaseName: syncbaseName}))
 
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 	for i := start; i < end; i++ {
 		var got string
 		key := fmt.Sprintf("%s%d", keyPrefix, i)
-		r := tb.Row(key)
+		r := c.Row(key)
 		if err := r.Get(ctx, &got); err != nil {
 			return fmt.Errorf("r.Get() failed: %v", err)
 		}
@@ -447,12 +447,12 @@
 	a := syncbase.NewService(syncbaseName).App("a")
 	d := a.Database("d", nil)
 
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 	var got string
 
 	// get first row
 	firstKey := fmt.Sprintf("%s%d", keyPrefix, start)
-	r := tb.Row(firstKey)
+	r := c.Row(firstKey)
 	if err := r.Get(ctx, &got); err != nil {
 		return fmt.Errorf("r.Get() failed: %v\n", err)
 	}
@@ -460,7 +460,7 @@
 
 	for i := start; i < end; i++ {
 		key := fmt.Sprintf("%s%d", keyPrefix, i)
-		r := tb.Row(key)
+		r := c.Row(key)
 		if err := r.Get(ctx, &got); err != nil {
 			return fmt.Errorf("r.Get() failed: %v\n", err)
 		}
@@ -480,8 +480,8 @@
 	a := syncbase.NewService(syncbaseName).App("a")
 	d := a.Database("d", schema)
 
-	tb := d.Table(testTable)
-	r := tb.Row(key)
+	c := d.Collection(testCollection)
+	r := c.Row(key)
 	want := valuePrefix + key
 
 	var value string
@@ -512,8 +512,8 @@
 }
 
 func waitSignal(ctx *context.T, d syncbase.Database, signalKey string) error {
-	tb := d.Table(testTable)
-	r := tb.Row(signalKey)
+	c := d.Collection(testCollection)
+	r := c.Row(signalKey)
 
 	var end bool
 	return testutil.RetryFor(10*time.Second, func() error {
@@ -538,9 +538,9 @@
 		Policy: wire.CrPolicy{
 			Rules: []wire.CrRule{
 				wire.CrRule{
-					TableName: testTable,
-					KeyPrefix: keyPrefix,
-					Resolver:  wire.ResolverTypeAppResolves,
+					CollectionName: testCollection,
+					KeyPrefix:      keyPrefix,
+					Resolver:       wire.ResolverTypeAppResolves,
 				},
 			},
 		},
diff --git a/syncbase/featuretests/ping_pong_test.go b/syncbase/featuretests/ping_pong_test.go
index 4318c6d..484f92d 100644
--- a/syncbase/featuretests/ping_pong_test.go
+++ b/syncbase/featuretests/ping_pong_test.go
@@ -28,11 +28,11 @@
 //
 // This benchmark performs the following operations:
 // - Create two syncbase instances and have them join the same syncgroup.
-// - Each watches the other syncbase's "section" of the table.
+// - Each watches the other syncbase's "section" of the collection.
 // - A preliminary write by each syncbase ensures that clocks are synced.
 // - During Ping Pong, each syncbase instance writes data to its own section of
-//   the table. The other syncbase watches that section for writes. Once a write
-//   is received, it does the same.
+//   the collection. The other syncbase watches that section for writes. Once a
+//   write is received, it does the same.
 //
 // After the benchmark completes, the "ns/op" value refers to the average time
 // for |pingPongPairIterations| of Ping Pong roundtrips completed.
@@ -61,12 +61,12 @@
 			sgSuffix := fmt.Sprintf("SG%d", g+1)
 			sgName := naming.Join(sbs[0].sbName, common.SyncbaseSuffix, sgSuffix)
 
-			// TODO(alexfandrianto): Was unable to use the empty prefix ("tb:").
+			// TODO(alexfandrianto): Was unable to use the empty prefix ("c:").
 			// Observation: w0's watch isn't working with the empty prefix.
 			// Possible explanation: The empty prefix ACL receives an initial value
-			// from the Table ACL. If this value is synced over from the opposing
+			// from the Collection ACL. If this value is synced over from the opposing
 			// peer, conflict resolution can mean that s0 loses the ability to watch.
-			syncString := fmt.Sprintf("%s:p", testTable)
+			syncString := fmt.Sprintf("%s:p", testCollection)
 			ok(b, createSyncgroup(sbs[0].clientCtx, sbs[0].sbName, sgName, syncString, "", sbBlessings(sbs), nil))
 
 			// The other syncbases will attempt to join the syncgroup.
@@ -76,19 +76,19 @@
 		}
 
 		// Obtain the handles to the databases.
-		db0, _ := getDbAndTable(sbs[0].sbName)
-		db1, _ := getDbAndTable(sbs[1].sbName)
+		db0, _ := getDbAndCollection(sbs[0].sbName)
+		db1, _ := getDbAndCollection(sbs[1].sbName)
 
 		// Setup the remaining syncbases
 		for i := 2; i < *numSync; i++ {
-			getDbAndTable(sbs[i].sbName)
+			getDbAndCollection(sbs[i].sbName)
 		}
 
 		// Set up the watch streams (watching the other syncbase's prefix).
 		prefix0, prefix1 := "prefix0", "prefix1"
-		w0, err := db0.Watch(sbs[0].clientCtx, testTable, prefix1, watch.ResumeMarker("now"))
+		w0, err := db0.Watch(sbs[0].clientCtx, testCollection, prefix1, watch.ResumeMarker("now"))
 		ok(b, err)
-		w1, err := db1.Watch(sbs[1].clientCtx, testTable, prefix0, watch.ResumeMarker("now"))
+		w1, err := db1.Watch(sbs[1].clientCtx, testCollection, prefix0, watch.ResumeMarker("now"))
 		ok(b, err)
 
 		// The join has succeeded, so make sure sync is initialized.
@@ -171,11 +171,12 @@
 	w.Cancel() // The stream can be canceled since we've seen enough iterations.
 }
 
-// getDbAndTable obtains the database and table handles for a syncbase name.
-func getDbAndTable(syncbaseName string) (d syncbase.Database, tb syncbase.Table) {
+// getDbAndCollection obtains the database and collection handles for a syncbase
+// name.
+func getDbAndCollection(syncbaseName string) (d syncbase.Database, c syncbase.Collection) {
 	a := syncbase.NewService(syncbaseName).App(testApp)
 	d = a.Database(testDb, nil)
-	tb = d.Table(testTable)
+	c = d.Collection(testCollection)
 	return
 }
 
@@ -183,12 +184,12 @@
 func writeInt32(ts *testSyncbase, keyPrefix string, keyValue int32) error {
 	ctx := ts.clientCtx
 	syncbaseName := ts.sbName
-	_, tb := getDbAndTable(syncbaseName)
+	_, c := getDbAndCollection(syncbaseName)
 
 	key := fmt.Sprintf("%s/%d", keyPrefix, keyValue)
 
-	if err := tb.Put(ctx, key, keyValue); err != nil {
-		return fmt.Errorf("tb.Put() failed: %v", err)
+	if err := c.Put(ctx, key, keyValue); err != nil {
+		return fmt.Errorf("c.Put() failed: %v", err)
 	}
 	return nil
 }
diff --git a/syncbase/featuretests/restartability_v23_test.go b/syncbase/featuretests/restartability_v23_test.go
index 530b959..1770198 100644
--- a/syncbase/featuretests/restartability_v23_test.go
+++ b/syncbase/featuretests/restartability_v23_test.go
@@ -38,7 +38,7 @@
 }
 
 // TODO(ivanpi): Duplicate of setupAppA.
-func createAppDatabaseTable(t *testing.T, clientCtx *context.T) syncbase.Database {
+func createAppDatabaseCollection(t *testing.T, clientCtx *context.T) syncbase.Database {
 	a := syncbase.NewService(testSbName).App("a")
 	if err := a.Create(clientCtx, nil); err != nil {
 		t.Fatalf("unable to create an app: %v", err)
@@ -47,8 +47,8 @@
 	if err := d.Create(clientCtx, nil); err != nil {
 		t.Fatalf("unable to create a database: %v", err)
 	}
-	if err := d.Table("tb").Create(clientCtx, nil); err != nil {
-		t.Fatalf("unable to create a table: %v", err)
+	if err := d.Collection("c").Create(clientCtx, nil); err != nil {
+		t.Fatalf("unable to create a collection: %v", err)
 	}
 	return d
 }
@@ -85,7 +85,7 @@
 	checkHierarchy(t, clientCtx)
 }
 
-// Creates apps, dbs, tables, and rows.
+// Creates apps, dbs, collections, and rows.
 func createHierarchy(t *testing.T, ctx *context.T) {
 	s := syncbase.NewService(testSbName)
 	for _, a := range []syncbase.App{s.App("a1"), s.App("a2")} {
@@ -96,13 +96,13 @@
 			if err := d.Create(ctx, nil); err != nil {
 				t.Fatalf("d.Create() failed: %v", err)
 			}
-			for _, tb := range []syncbase.Table{d.Table("tb1"), d.Table("tb2")} {
-				if err := d.Table(tb.Name()).Create(ctx, nil); err != nil {
-					t.Fatalf("d.CreateTable() failed: %v", err)
+			for _, c := range []syncbase.Collection{d.Collection("c1"), d.Collection("c2")} {
+				if err := d.Collection(c.Name()).Create(ctx, nil); err != nil {
+					t.Fatalf("d.CreateCollection() failed: %v", err)
 				}
 				for _, k := range []string{"foo", "bar"} {
-					if err := tb.Put(ctx, k, k); err != nil {
-						t.Fatalf("tb.Put() failed: %v", err)
+					if err := c.Put(ctx, k, k); err != nil {
+						t.Fatalf("c.Put() failed: %v", err)
 					}
 				}
 			}
@@ -110,7 +110,7 @@
 	}
 }
 
-// Checks for the apps, dbs, tables, and rows created by runCreateHierarchy.
+// Checks for the apps, dbs, collections, and rows created by runCreateHierarchy.
 func checkHierarchy(t *testing.T, ctx *context.T) {
 	s := syncbase.NewService(testSbName)
 	var got, want []string
@@ -136,16 +136,16 @@
 		}
 		for _, dName := range want {
 			d := a.Database(dName, nil)
-			if got, err = d.ListTables(ctx); err != nil {
-				t.Fatalf("d.ListTables() failed: %v", err)
+			if got, err = d.ListCollections(ctx); err != nil {
+				t.Fatalf("d.ListCollections() failed: %v", err)
 			}
-			want = []string{"tb1", "tb2"}
+			want = []string{"c1", "c2"}
 			if !reflect.DeepEqual(got, want) {
-				t.Fatalf("Tables do not match: got %v, want %v", got, want)
+				t.Fatalf("Collections do not match: got %v, want %v", got, want)
 			}
-			for _, tbName := range want {
-				tb := d.Table(tbName)
-				if err := tu.ScanMatches(ctx, tb, syncbase.Prefix(""), []string{"bar", "foo"}, []interface{}{"bar", "foo"}); err != nil {
+			for _, cName := range want {
+				c := d.Collection(cName)
+				if err := tu.ScanMatches(ctx, c, syncbase.Prefix(""), []string{"bar", "foo"}, []interface{}{"bar", "foo"}); err != nil {
 					t.Fatalf("Scan does not match: %v", err)
 				}
 			}
@@ -159,12 +159,12 @@
 	defer sh.Cleanup()
 	rootDir, clientCtx, serverCreds := restartabilityInit(sh)
 	cleanup := sh.StartSyncbase(serverCreds, syncbaselib.Opts{Name: testSbName, RootDir: rootDir}, acl)
-	d := createAppDatabaseTable(t, clientCtx)
+	d := createAppDatabaseCollection(t, clientCtx)
 
-	tb := d.Table("tb")
+	c := d.Collection("c")
 
 	// Do Put followed by Get on a row.
-	r := tb.Row("r")
+	r := c.Row("r")
 	if err := r.Put(clientCtx, "testkey"); err != nil {
 		t.Fatalf("r.Put() failed: %v", err)
 	}
@@ -195,10 +195,10 @@
 	defer sh.Cleanup()
 	rootDir, clientCtx, serverCreds := restartabilityInit(sh)
 	cleanup := sh.StartSyncbase(serverCreds, syncbaselib.Opts{Name: testSbName, RootDir: rootDir}, acl)
-	d := createAppDatabaseTable(t, clientCtx)
+	d := createAppDatabaseCollection(t, clientCtx)
 
 	// Add one row.
-	if err := d.Table("tb").Row("r").Put(clientCtx, "testkey"); err != nil {
+	if err := d.Collection("c").Row("r").Put(clientCtx, "testkey"); err != nil {
 		t.Fatalf("r.Put() failed: %v", err)
 	}
 
@@ -206,8 +206,8 @@
 	if err != nil {
 		t.Fatalf("unable to start batch: %v", err)
 	}
-	tb := batch.Table("tb")
-	r := tb.Row("r")
+	c := batch.Collection("c")
+	r := c.Row("r")
 
 	var result string
 	if err := r.Get(clientCtx, &result); err != nil {
@@ -236,7 +236,7 @@
 	}
 
 	// Try to get the row outside of a batch.  It should exist.
-	if err := d.Table("tb").Row("r").Get(clientCtx, &result); err != nil {
+	if err := d.Collection("c").Row("r").Get(clientCtx, &result); err != nil {
 		t.Fatalf("unexpected error: %v", err)
 	}
 }
@@ -248,16 +248,16 @@
 	defer sh.Cleanup()
 	rootDir, clientCtx, serverCreds := restartabilityInit(sh)
 	cleanup := sh.StartSyncbase(serverCreds, syncbaselib.Opts{Name: testSbName, RootDir: rootDir}, acl)
-	d := createAppDatabaseTable(t, clientCtx)
+	d := createAppDatabaseCollection(t, clientCtx)
 
 	batch, err := d.BeginBatch(clientCtx, wire.BatchOptions{})
 	if err != nil {
 		t.Fatalf("unable to start batch: %v", err)
 	}
-	tb := batch.Table("tb")
+	c := batch.Collection("c")
 
 	// Do Put followed by Get on a row.
-	r := tb.Row("r")
+	r := c.Row("r")
 	if err := r.Put(clientCtx, "testkey"); err != nil {
 		t.Fatalf("r.Put() failed: %v", err)
 	}
@@ -288,7 +288,7 @@
 	}
 
 	// Try to get the row outside of a batch.  It should not exist.
-	if err := d.Table("tb").Row("r").Get(clientCtx, &result); verror.ErrorID(err) != verror.ErrNoExist.ID {
+	if err := d.Collection("c").Row("r").Get(clientCtx, &result); verror.ErrorID(err) != verror.ErrNoExist.ID {
 		t.Fatalf("expected r.Get() to fail because of ErrNoExist.  got: %v", err)
 	}
 }
@@ -307,7 +307,7 @@
 	defer sh.Cleanup()
 	rootDir, clientCtx, serverCreds := restartabilityInit(sh)
 	cleanup := sh.StartSyncbase(serverCreds, syncbaselib.Opts{Name: testSbName, RootDir: rootDir}, acl)
-	d := createAppDatabaseTable(t, clientCtx)
+	d := createAppDatabaseCollection(t, clientCtx)
 
 	// Put one row as well as get the initial ResumeMarker.
 	batch, err := d.BeginBatch(clientCtx, wire.BatchOptions{})
@@ -318,7 +318,7 @@
 	if err != nil {
 		t.Fatalf("unexpected error: %v", err)
 	}
-	r := batch.Table("tb").Row("r")
+	r := batch.Collection("c").Row("r")
 	if err := r.Put(clientCtx, "testvalue1"); err != nil {
 		t.Fatalf("r.Put() failed: %v", err)
 	}
@@ -328,7 +328,7 @@
 
 	// Watch for the row change.
 	timeout, _ := context.WithTimeout(clientCtx, time.Second)
-	stream, err := d.Watch(timeout, "tb", "r", marker)
+	stream, err := d.Watch(timeout, "c", "r", marker)
 	if err != nil {
 		t.Fatalf("unexpected error: %v", err)
 	}
@@ -355,14 +355,14 @@
 	cleanup = sh.StartSyncbase(serverCreds, syncbaselib.Opts{Name: testSbName, RootDir: rootDir}, acl)
 
 	// Put another row.
-	r = d.Table("tb").Row("r")
+	r = d.Collection("c").Row("r")
 	if err := r.Put(clientCtx, "testvalue2"); err != nil {
 		t.Fatalf("r.Put() failed: %v", err)
 	}
 
 	// Resume the watch from after the first Put.  We should see only the second
 	// Put.
-	stream, err = d.Watch(clientCtx, "tb", "", marker)
+	stream, err = d.Watch(clientCtx, "c", "", marker)
 	if err != nil {
 		t.Fatalf("unexpected error: %v", err)
 	}
@@ -488,13 +488,13 @@
 	if err := d.Create(clientCtx, nil); err != nil {
 		t.Fatalf("d.Create() failed: %v", err)
 	}
-	for _, tb := range []syncbase.Table{d.Table("tb1"), d.Table("tb2")} {
-		if err := tb.Create(clientCtx, nil); err != nil {
-			t.Fatalf("d.CreateTable() failed: %v", err)
+	for _, c := range []syncbase.Collection{d.Collection("c1"), d.Collection("c2")} {
+		if err := c.Create(clientCtx, nil); err != nil {
+			t.Fatalf("d.CreateCollection() failed: %v", err)
 		}
 		for _, k := range []string{"foo", "bar"} {
-			if err := tb.Put(clientCtx, k, k); err != nil {
-				t.Fatalf("tb.Put() failed: %v", err)
+			if err := c.Put(clientCtx, k, k); err != nil {
+				t.Fatalf("c.Put() failed: %v", err)
 			}
 		}
 	}
diff --git a/syncbase/featuretests/syncgroup_v23_test.go b/syncbase/featuretests/syncgroup_v23_test.go
index 65e0d15..196d911 100644
--- a/syncbase/featuretests/syncgroup_v23_test.go
+++ b/syncbase/featuretests/syncgroup_v23_test.go
@@ -37,7 +37,7 @@
 	// Syncbase s0 is the creator.
 	sgName := naming.Join(sbs[0].sbName, common.SyncbaseSuffix, "SG1")
 
-	ok(t, createSyncgroup(sbs[0].clientCtx, sbs[0].sbName, sgName, "tb:foo", "", sbBlessings(sbs), nil))
+	ok(t, createSyncgroup(sbs[0].clientCtx, sbs[0].sbName, sgName, "c:foo", "", sbBlessings(sbs), nil))
 
 	// Remaining syncbases run the specified workload concurrently.
 	for i := 1; i < len(sbs); i++ {
@@ -79,7 +79,7 @@
 	// Syncbase s0 is the creator, and sN is the cloud.
 	sgName := naming.Join(sbs[N].sbName, common.SyncbaseSuffix, "SG1")
 
-	ok(t, createSyncgroup(sbs[0].clientCtx, sbs[0].sbName, sgName, "tb:foo", "", sbBlessings(sbs), nil))
+	ok(t, createSyncgroup(sbs[0].clientCtx, sbs[0].sbName, sgName, "c:foo", "", sbBlessings(sbs), nil))
 
 	// Remaining N-1 syncbases run the specified workload concurrently.
 	for i := 1; i < N; i++ {
@@ -136,7 +136,7 @@
 	}
 	perms.Add(security.BlessingPattern("root:"+sbs[0].sbName), string(access.Admin))
 
-	ok(t, createSyncgroup(sbs[0].clientCtx, sbs[0].sbName, sgName, "tb:foo", "/mttable", "", perms))
+	ok(t, createSyncgroup(sbs[0].clientCtx, sbs[0].sbName, sgName, "c:foo", "/mttable", "", perms))
 
 	// Remaining syncbases run the specified workload concurrently.
 	for i := 1; i < len(sbs); i++ {
@@ -175,12 +175,12 @@
 	// Syncbase s0 is the first to join or create. Run s0 separately to
 	// stagger the process.
 	sgName := naming.Join(sbs[0].sbName, common.SyncbaseSuffix, "SG1")
-	ok(t, joinOrCreateSyncgroup(sbs[0].clientCtx, sbs[0].sbName, sgName, "tb:foo", "", sbBlessings(sbs)))
+	ok(t, joinOrCreateSyncgroup(sbs[0].clientCtx, sbs[0].sbName, sgName, "c:foo", "", sbBlessings(sbs)))
 
 	// Remaining syncbases run the specified workload concurrently.
 	for i := 1; i < len(sbs); i++ {
 		go func(i int) {
-			ok(t, joinOrCreateSyncgroup(sbs[i].clientCtx, sbs[i].sbName, sgName, "tb:foo", "", sbBlessings(sbs)))
+			ok(t, joinOrCreateSyncgroup(sbs[i].clientCtx, sbs[i].sbName, sgName, "c:foo", "", sbBlessings(sbs)))
 		}(i)
 	}
 
diff --git a/syncbase/featuretests/test_util_test.go b/syncbase/featuretests/test_util_test.go
index 37769ce..e14d0b5 100644
--- a/syncbase/featuretests/test_util_test.go
+++ b/syncbase/featuretests/test_util_test.go
@@ -25,10 +25,10 @@
 )
 
 const (
-	testSbName = "syncbase" // Name that syncbase mounts itself at.
-	testApp    = "a"
-	testDb     = "d"
-	testTable  = "tb"
+	testSbName     = "syncbase" // Name that syncbase mounts itself at.
+	testApp        = "a"
+	testDb         = "d"
+	testCollection = "c"
 )
 
 ////////////////////////////////////////////////////////////
@@ -43,7 +43,7 @@
 	if err := d.Create(ctx, nil); err != nil {
 		return err
 	}
-	return d.Table(testTable).Create(ctx, nil)
+	return d.Collection(testCollection).Create(ctx, nil)
 }
 
 type testSyncbase struct {
@@ -95,12 +95,12 @@
 
 	a := syncbase.NewService(syncbaseName).App(testApp)
 	d := a.Database(testDb, nil)
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	for i := start; i < end; i++ {
 		key := fmt.Sprintf("%s%d", keyPrefix, i)
-		if err := tb.Put(ctx, key, "testkey"+key); err != nil {
-			return fmt.Errorf("tb.Put() failed: %v", err)
+		if err := c.Put(ctx, key, "testkey"+key); err != nil {
+			return fmt.Errorf("c.Put() failed: %v", err)
 		}
 	}
 	return nil
@@ -118,11 +118,11 @@
 		valuePrefix = "testkey"
 	}
 
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 	for i := start; i < end; i++ {
 		key := fmt.Sprintf("foo%d", i)
-		if err := tb.Put(ctx, key, valuePrefix+syncbaseName+key); err != nil {
-			return fmt.Errorf("tb.Put() failed: %v", err)
+		if err := c.Put(ctx, key, valuePrefix+syncbaseName+key); err != nil {
+			return fmt.Errorf("c.Put() failed: %v", err)
 		}
 	}
 	return nil
@@ -160,8 +160,8 @@
 // TODO(ivanpi): Remove sendSignal now that all functions using it are in the
 // same process.
 func sendSignal(ctx *context.T, d syncbase.Database, signalKey string) error {
-	tb := d.Table(testTable)
-	r := tb.Row(signalKey)
+	c := d.Collection(testCollection)
+	r := c.Row(signalKey)
 
 	if err := r.Put(ctx, true); err != nil {
 		return fmt.Errorf("r.Put() failed: %v", err)
@@ -177,14 +177,14 @@
 func verifySyncgroupData(ctx *context.T, syncbaseName, keyPrefix string, start, count int) error {
 	a := syncbase.NewService(syncbaseName).App(testApp)
 	d := a.Database(testDb, nil)
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	// Wait a bit (up to 10 seconds) for the last key to appear.
 	lastKey := fmt.Sprintf("%s%d", keyPrefix, start+count-1)
 	for i := 0; i < 20; i++ {
 		time.Sleep(500 * time.Millisecond)
 		var value string
-		if err := tb.Get(ctx, lastKey, &value); err == nil {
+		if err := c.Get(ctx, lastKey, &value); err == nil {
 			break
 		}
 	}
@@ -193,8 +193,8 @@
 	for i := start; i < start+count; i++ {
 		key := fmt.Sprintf("%s%d", keyPrefix, i)
 		var got string
-		if err := tb.Get(ctx, key, &got); err != nil {
-			return fmt.Errorf("tb.Get() failed: %v", err)
+		if err := c.Get(ctx, key, &got); err != nil {
+			return fmt.Errorf("c.Get() failed: %v", err)
 		}
 		want := "testkey" + key
 		if got != want {
@@ -205,7 +205,7 @@
 	// TODO(sadovsky): Drop this? (Does it buy us much?)
 	if !skipScan {
 		// Re-verify using a scan operation.
-		stream := tb.Scan(ctx, syncbase.Prefix(keyPrefix))
+		stream := c.Scan(ctx, syncbase.Prefix(keyPrefix))
 		for i := 0; stream.Advance(); i++ {
 			got, want := stream.Key(), fmt.Sprintf("%s%d", keyPrefix, i)
 			if got != want {
@@ -308,16 +308,16 @@
 // Syncbase-specific testing helpers
 
 // parseSgPrefixes converts, for example, "a:b,c:" to
-// [{TableName: testApp, Row: "b"}, {TableName: "c", Row: ""}].
-func parseSgPrefixes(csv string) []wire.TableRow {
+// [{CollectionName: testApp, Row: "b"}, {CollectionName: "c", Row: ""}].
+func parseSgPrefixes(csv string) []wire.CollectionRow {
 	strs := strings.Split(csv, ",")
-	res := make([]wire.TableRow, len(strs))
+	res := make([]wire.CollectionRow, len(strs))
 	for i, v := range strs {
 		parts := strings.SplitN(v, ":", 2)
 		if len(parts) != 2 {
 			panic(fmt.Sprintf("invalid prefix string: %q", v))
 		}
-		res[i] = wire.TableRow{TableName: parts[0], Row: parts[1]}
+		res[i] = wire.CollectionRow{CollectionName: parts[0], Row: parts[1]}
 	}
 	return res
 }
diff --git a/syncbase/featuretests/vclock_v23_test.go b/syncbase/featuretests/vclock_v23_test.go
index 31fbbde..f08e214 100644
--- a/syncbase/featuretests/vclock_v23_test.go
+++ b/syncbase/featuretests/vclock_v23_test.go
@@ -398,7 +398,7 @@
 		}
 		a, b := sbs[i], sbs[i+1]
 		sgName := naming.Join(a.sbName, common.SyncbaseSuffix, "syncgroup")
-		ok(t, createSyncgroup(a.clientCtx, a.sbName, sgName, testTable+":"+a.sbName+b.sbName, "", "root", nil))
+		ok(t, createSyncgroup(a.clientCtx, a.sbName, sgName, testCollection+":"+a.sbName+b.sbName, "", "root", nil))
 		ok(t, joinSyncgroup(b.clientCtx, b.sbName, sgName))
 		// Wait for a to see b.
 		ok(t, verifySyncgroupMembers(a.clientCtx, a.sbName, sgName, 2))
diff --git a/syncbase/model.go b/syncbase/model.go
index 4098850..be7f4cf 100644
--- a/syncbase/model.go
+++ b/syncbase/model.go
@@ -84,12 +84,12 @@
 	// FullName returns the object name (escaped) of this DatabaseHandle.
 	FullName() string
 
-	// Table returns the Table with the given name.
+	// Collection returns the Collection with the given name.
 	// relativeName must not contain slashes.
-	Table(relativeName string) Table
+	Collection(relativeName string) Collection
 
-	// ListTables returns a list of all Table names.
-	ListTables(ctx *context.T) ([]string, error)
+	// ListCollections returns a list of all Collection names.
+	ListCollections(ctx *context.T) ([]string, error)
 
 	// Exec executes a syncQL query.
 	// A value must be provided for every positional parameter ('?' placeholder)
@@ -122,7 +122,7 @@
 	Close()
 }
 
-// Database represents a collection of Tables. Batches, queries, sync, watch,
+// Database represents a set of Collections. Batches, queries, sync, watch,
 // etc. all operate at the Database level.
 type Database interface {
 	DatabaseHandle
@@ -176,7 +176,7 @@
 	//
 	// TODO(sadovsky): Watch should return just a WatchStream, similar to how Scan
 	// returns just a ScanStream.
-	Watch(ctx *context.T, table, prefix string, resumeMarker watch.ResumeMarker) (WatchStream, error)
+	Watch(ctx *context.T, collection, prefix string, resumeMarker watch.ResumeMarker) (WatchStream, error)
 
 	// Syncgroup returns a handle to the syncgroup with the given name.
 	Syncgroup(sgName string) Syncgroup
@@ -233,37 +233,37 @@
 	Perms  access.Permissions
 }
 
-// Table represents a collection of Rows.
+// Collection represents a set of Rows.
 //
-// TODO(sadovsky): Currently we provide Get/Put/Delete methods on both Table and
-// Row, because we're not sure which will feel more natural. Eventually, we'll
-// need to pick one.
-type Table interface {
-	// Name returns the relative name of this Table.
+// TODO(sadovsky): Currently we provide Get/Put/Delete methods on both
+// Collection and Row, because we're not sure which will feel more natural.
+// Eventually, we'll need to pick one.
+type Collection interface {
+	// Name returns the relative name of this Collection.
 	Name() string
 
-	// FullName returns the object name (escaped) of this Table.
+	// FullName returns the object name (escaped) of this Collection.
 	FullName() string
 
-	// Exists returns true only if this Table exists. Insufficient permissions
+	// Exists returns true only if this Collection exists. Insufficient permissions
 	// cause Exists to return false instead of an error.
 	// TODO(ivanpi): Exists may fail with an error if higher levels of hierarchy
 	// do not exist.
 	Exists(ctx *context.T) (bool, error)
 
-	// Create creates this Table.
+	// Create creates this Collection.
 	// If perms is nil, we inherit (copy) the Database perms.
 	// Create must not be called from within a batch.
 	Create(ctx *context.T, perms access.Permissions) error
 
-	// Destroy destroys this Table, permanently removing all of its data.
+	// Destroy destroys this Collection, permanently removing all of its data.
 	// Destroy must not be called from within a batch.
 	Destroy(ctx *context.T) error
 
-	// GetPermissions returns the current Permissions for the Table.
+	// GetPermissions returns the current Permissions for the Collection.
 	GetPermissions(ctx *context.T) (access.Permissions, error)
 
-	// SetPermissions replaces the current Permissions for the Table.
+	// SetPermissions replaces the current Permissions for the Collection.
 	SetPermissions(ctx *context.T, perms access.Permissions) error
 
 	// Row returns the Row with the given primary key.
@@ -272,12 +272,12 @@
 	// Get stores the value for the given primary key in value. If value's type
 	// does not match the stored type, Get will return an error. Expected usage:
 	//     var val mytype
-	//     if err := table.Get(ctx, key, &val); err != nil {
+	//     if err := collection.Get(ctx, key, &val); err != nil {
 	//       return err
 	//     }
 	Get(ctx *context.T, key string, value interface{}) error
 
-	// Put writes the given value to this Table. The value's primary key field
+	// Put writes the given value to this Collection. The value's primary key field
 	// must be set.
 	// TODO(kash): Can VOM handle everything that satisfies interface{}?
 	// Need to talk to Todd.
@@ -307,7 +307,7 @@
 	// GetPrefixPermissions returns an array of (prefix, perms) pairs. The array is
 	// sorted from longest prefix to shortest, so element zero is the one that
 	// applies to the row with the given key. The last element is always the
-	// prefix "" which represents the table's permissions -- the array will always
+	// prefix "" which represents the collection's permissions -- the array will always
 	// have at least one element.
 	GetPrefixPermissions(ctx *context.T, key string) ([]PrefixPermissions, error)
 
@@ -326,7 +326,7 @@
 	DeletePrefixPermissions(ctx *context.T, prefix PrefixRange) error
 }
 
-// Row represents a single row in a Table.
+// Row represents a single row in a Collection.
 type Row interface {
 	// Key returns the primary key for this Row.
 	Key() string
@@ -421,16 +421,16 @@
 
 // WatchChange is the new value for a watched entity.
 type WatchChange struct {
-	// Table is the name of the table that contains the changed row.
-	Table string
+	// Collection is the name of the collection that contains the changed row.
+	Collection string
 
 	// Row is the key of the changed row.
 	Row string
 
 	// ChangeType describes the type of the change. If the ChangeType equals to
-	// PutChange, then the row exists in the table and the Value contains the new
+	// PutChange, then the row exists in the collection and the Value contains the new
 	// value for this row. If the state equals to DeleteChange, then the row was
-	// removed from the table.
+	// removed from the collection.
 	ChangeType ChangeType
 
 	// ValueBytes is the new VOM-encoded value for the row if the ChangeType is
diff --git a/syncbase/permissions_test.go b/syncbase/permissions_test.go
index 7170c35..a0f93ee 100644
--- a/syncbase/permissions_test.go
+++ b/syncbase/permissions_test.go
@@ -27,11 +27,11 @@
 }
 
 type databaseTest struct {
-	f func(ctx *context.T, db syncbase.Database) error
+	f func(ctx *context.T, d syncbase.Database) error
 }
 
-type tableTest struct {
-	f func(ctx *context.T, tb syncbase.Table) error
+type collectionTest struct {
+	f func(ctx *context.T, c syncbase.Collection) error
 }
 
 type rowTest struct {
@@ -122,21 +122,21 @@
 
 	// Database tests.
 	{
-		layer: databaseTest{f: func(ctx *context.T, db syncbase.Database) error {
-			_, _, err := db.GetPermissions(ctx)
+		layer: databaseTest{f: func(ctx *context.T, d syncbase.Database) error {
+			_, _, err := d.GetPermissions(ctx)
 			return err
 		}},
 		name:     "database.GetPermissions",
 		patterns: []string{"__A___"},
 	},
 
-	// Table tests.
+	// Collection tests.
 	{
-		layer: tableTest{f: func(ctx *context.T, tb syncbase.Table) error {
-			_, err := tb.GetPermissions(ctx)
+		layer: collectionTest{f: func(ctx *context.T, c syncbase.Collection) error {
+			_, err := c.GetPermissions(ctx)
 			return err
 		}},
-		name:     "table.GetPermissions",
+		name:     "collection.GetPermissions",
 		patterns: []string{"___A__"},
 	},
 
@@ -163,7 +163,7 @@
 // 0 - service ACL
 // 1 - app ACL
 // 2 - database ACL
-// 3 - table ACL
+// 3 - collection ACL
 // 4 - longest prefix ACL
 // 5 - syncgroup ACL
 // A pattern defines a set of per-ACL permissions required for a client to call
@@ -184,7 +184,7 @@
 // Then we pack all tests into runs, where each run has only one type of tests
 // (allowed or denied) and at most one mutating test. For each run we rebuild
 // the following Syncbase structure:
-// service: s; app a; database db; table tb; row prefix (with ACL at 'prefix').
+// service: s; app a; database d; collection c; row prefix (with ACL at 'prefix').
 //
 // For each test inside a run we generate 6 huge ACLs with a record for each
 // of the test + one admin record.
@@ -254,14 +254,14 @@
 	addPerms(appPerms, 1, tests...)
 	databasePerms := tu.DefaultPerms("root:admin")
 	addPerms(databasePerms, 2, tests...)
-	tablePerms := tu.DefaultPerms("root:admin")
-	addPerms(tablePerms, 3, tests...)
+	collectionPerms := tu.DefaultPerms("root:admin")
+	addPerms(collectionPerms, 3, tests...)
 	rowPerms := tu.DefaultPerms("root:admin")
 	addPerms(rowPerms, 4, tests...)
 	sgPerms := tu.DefaultPerms("root:admin")
 	addPerms(sgPerms, 5, tests...)
 
-	// Create service/app/database/table/row with permissions above.
+	// Create service/app/database/collection/row with permissions above.
 	ctx, adminCtx, sName, rootp, cleanup := tu.SetupOrDieCustom("admin", "server", nil)
 	defer cleanup()
 	s := syncbase.NewService(sName)
@@ -272,21 +272,21 @@
 	if err := a.Create(adminCtx, appPerms); err != nil {
 		tu.Fatalf(t, "a.Create failed: %v", err)
 	}
-	db := a.Database("db", nil)
-	if err := db.Create(adminCtx, databasePerms); err != nil {
-		tu.Fatalf(t, "db.Create failed: %v", err)
+	d := a.Database("d", nil)
+	if err := d.Create(adminCtx, databasePerms); err != nil {
+		tu.Fatalf(t, "d.Create failed: %v", err)
 	}
-	tb := db.Table("tb")
-	if err := tb.Create(adminCtx, tablePerms); err != nil {
-		tu.Fatalf(t, "db.Create failed: %v", err)
+	c := d.Collection("c")
+	if err := c.Create(adminCtx, collectionPerms); err != nil {
+		tu.Fatalf(t, "d.Create failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(adminCtx, syncbase.Prefix(""), rowPerms); err != nil {
-		tu.Fatalf(t, "tb.SetPrefixPermissions failed: %v", err)
+	if err := c.SetPrefixPermissions(adminCtx, syncbase.Prefix(""), rowPerms); err != nil {
+		tu.Fatalf(t, "c.SetPrefixPermissions failed: %v", err)
 	}
-	if err := tb.SetPrefixPermissions(adminCtx, syncbase.Prefix("prefix"), rowPerms); err != nil {
-		tu.Fatalf(t, "tb.SetPrefixPermissions failed: %v", err)
+	if err := c.SetPrefixPermissions(adminCtx, syncbase.Prefix("prefix"), rowPerms); err != nil {
+		tu.Fatalf(t, "c.SetPrefixPermissions failed: %v", err)
 	}
-	r := tb.Row("prefix")
+	r := c.Row("prefix")
 	r.Put(adminCtx, "value")
 
 	// Verify tests.
@@ -299,9 +299,9 @@
 		case appTest:
 			err = layer.f(clientCtx, a)
 		case databaseTest:
-			err = layer.f(clientCtx, db)
-		case tableTest:
-			err = layer.f(clientCtx, tb)
+			err = layer.f(clientCtx, d)
+		case collectionTest:
+			err = layer.f(clientCtx, c)
 		case rowTest:
 			err = layer.f(clientCtx, r)
 		}
diff --git a/syncbase/scan_stream.go b/syncbase/scan_stream.go
index 8df0a57..ab6a7a8 100644
--- a/syncbase/scan_stream.go
+++ b/syncbase/scan_stream.go
@@ -18,7 +18,7 @@
 	// cancel cancels the RPC stream.
 	cancel context.CancelFunc
 	// call is the RPC stream object.
-	call wire.TableScanClientCall
+	call wire.CollectionScanClientCall
 	// curr is the currently staged key-value pair, or nil if nothing is staged.
 	curr *wire.KeyValue
 	// err is the first error encountered during streaming. It may also be
@@ -30,7 +30,7 @@
 
 var _ ScanStream = (*scanStream)(nil)
 
-func newScanStream(cancel context.CancelFunc, call wire.TableScanClientCall) *scanStream {
+func newScanStream(cancel context.CancelFunc, call wire.CollectionScanClientCall) *scanStream {
 	return &scanStream{
 		cancel: cancel,
 		call:   call,
diff --git a/syncbase/schema_test.go b/syncbase/schema_test.go
index 1f37b87..6a7586e 100644
--- a/syncbase/schema_test.go
+++ b/syncbase/schema_test.go
@@ -45,7 +45,7 @@
 	// try to make a new database object for the same database but this time
 	// with a new schema version
 	schema.Metadata.Version = 1
-	rule := wire.CrRule{"table1", "foo", "", wire.ResolverTypeLastWins}
+	rule := wire.CrRule{"collection1", "foo", "", wire.ResolverTypeLastWins}
 	policy := wire.CrPolicy{
 		Rules: []wire.CrRule{rule},
 	}
@@ -78,16 +78,16 @@
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	schema := tu.DefaultSchema(0)
 
-	// Create db1 with schema version 0 and add table1 and row1
+	// Create db1 with schema version 0 and add collection1 and row1
 	dbHandle1 := a.Database("db1", schema)
 	if err := dbHandle1.Create(ctx, nil); err != nil {
 		t.Fatalf("db1.Create() failed: %v", err)
 	}
-	if err := dbHandle1.Table("table1").Create(ctx, nil); err != nil {
-		t.Fatalf("db1.CreateTable() failed: %v", err)
+	if err := dbHandle1.Collection("collection1").Create(ctx, nil); err != nil {
+		t.Fatalf("db1.CreateCollection() failed: %v", err)
 	}
-	if err := dbHandle1.Table("table1").Put(ctx, "row1", "value1"); err != nil {
-		t.Fatalf("table1.Put() failed: %v", err)
+	if err := dbHandle1.Collection("collection1").Put(ctx, "row1", "value1"); err != nil {
+		t.Fatalf("collection1.Put() failed: %v", err)
 	}
 
 	// Try writing to database db1 with a db handle with schema version 2
@@ -95,10 +95,10 @@
 	dbHandle2 := a.Database("db1", schema2)
 
 	// verify write rpcs for Database
-	if err := dbHandle2.Table("table1").Create(ctx, nil); !isVersionMismatchErr(err) {
+	if err := dbHandle2.Collection("collection1").Create(ctx, nil); !isVersionMismatchErr(err) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
-	if err := dbHandle2.Table("table1").Destroy(ctx); !isVersionMismatchErr(err) {
+	if err := dbHandle2.Collection("collection1").Destroy(ctx); !isVersionMismatchErr(err) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
 	if err := dbHandle2.Destroy(ctx); !isVersionMismatchErr(err) {
@@ -114,39 +114,39 @@
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
 
-	// verify write rpcs for Table
-	table := dbHandle2.Table("table1")
-	if _, err := table.Exists(ctx); !isVersionMismatchErr(err) {
+	// verify write rpcs for Collection
+	collection := dbHandle2.Collection("collection1")
+	if _, err := collection.Exists(ctx); !isVersionMismatchErr(err) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
-	if err := table.Delete(ctx, "row1"); !isVersionMismatchErr(err) {
+	if err := collection.Delete(ctx, "row1"); !isVersionMismatchErr(err) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
-	stream := table.Scan(ctx, syncbase.SingleRow("row1"))
+	stream := collection.Scan(ctx, syncbase.SingleRow("row1"))
 	if stream.Advance() {
 		t.Fatalf("Stream advanced unexpectedly")
 	}
 	if !isVersionMismatchErr(stream.Err()) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(stream.Err()))
 	}
-	if _, err := table.GetPermissions(ctx); !isVersionMismatchErr(err) {
+	if _, err := collection.GetPermissions(ctx); !isVersionMismatchErr(err) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
-	if err := table.SetPermissions(ctx, nil); !isVersionMismatchErr(err) {
+	if err := collection.SetPermissions(ctx, nil); !isVersionMismatchErr(err) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
-	if _, err := table.GetPrefixPermissions(ctx, "row1"); !isVersionMismatchErr(err) {
+	if _, err := collection.GetPrefixPermissions(ctx, "row1"); !isVersionMismatchErr(err) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
-	if err := table.SetPrefixPermissions(ctx, syncbase.Prefix("row"), nil); !isVersionMismatchErr(err) {
+	if err := collection.SetPrefixPermissions(ctx, syncbase.Prefix("row"), nil); !isVersionMismatchErr(err) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
-	if err := table.DeletePrefixPermissions(ctx, syncbase.Prefix("row")); !isVersionMismatchErr(err) {
+	if err := collection.DeletePrefixPermissions(ctx, syncbase.Prefix("row")); !isVersionMismatchErr(err) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
 
 	// verify write rpcs for Row
-	row := table.Row("row1")
+	row := collection.Row("row1")
 	if _, err := row.Exists(ctx); !isVersionMismatchErr(err) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
@@ -169,16 +169,16 @@
 	a := tu.CreateApp(t, ctx, syncbase.NewService(sName), "a")
 	schema := tu.DefaultSchema(0)
 
-	// Create db1 with schema version 0 and add table1 and row1
+	// Create db1 with schema version 0 and add collection1 and row1
 	dbHandle1 := a.Database("db1", schema)
 	if err := dbHandle1.Create(ctx, nil); err != nil {
 		t.Fatalf("db1.Create() failed: %v", err)
 	}
-	if err := dbHandle1.Table("table1").Create(ctx, nil); err != nil {
-		t.Fatalf("db1.CreateTable() failed: %v", err)
+	if err := dbHandle1.Collection("collection1").Create(ctx, nil); err != nil {
+		t.Fatalf("db1.CreateCollection() failed: %v", err)
 	}
-	if err := dbHandle1.Table("table1").Put(ctx, "row1", "value1"); err != nil {
-		t.Fatalf("table1.Put() failed: %v", err)
+	if err := dbHandle1.Collection("collection1").Put(ctx, "row1", "value1"); err != nil {
+		t.Fatalf("collection1.Put() failed: %v", err)
 	}
 
 	// Create three batches using dbHandle1
@@ -186,13 +186,13 @@
 	if batchErr1 != nil {
 		t.Fatalf("db1.BeginBatch() failed: %v", batchErr1)
 	}
-	batch1.Table("table1").Row("row1").Put(ctx, "newValue1")
+	batch1.Collection("collection1").Row("row1").Put(ctx, "newValue1")
 
 	batch2, batchErr2 := dbHandle1.BeginBatch(ctx, wire.BatchOptions{})
 	if batchErr2 != nil {
 		t.Fatalf("db1.BeginBatch() failed: %v", batchErr2)
 	}
-	batch2.Table("table1").Row("row1").Put(ctx, "newValue2")
+	batch2.Collection("collection1").Row("row1").Put(ctx, "newValue2")
 
 	batch3, batchErr3 := dbHandle1.BeginBatch(ctx, wire.BatchOptions{})
 	if batchErr3 != nil {
@@ -212,14 +212,14 @@
 	if err := batch2.Abort(ctx); !isVersionMismatchErr(err) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
-	if err := batch3.Table("table1").Row("row1").Put(ctx, "newValue3"); !isVersionMismatchErr(err) {
+	if err := batch3.Collection("collection1").Row("row1").Put(ctx, "newValue3"); !isVersionMismatchErr(err) {
 		t.Fatal("Expected ErrDatabaseVersionMismatch, found: " + toString(err))
 	}
 
 	// Verify that the value of row1 is the original value.
 	var value string
-	if err := dbHandle2.Table("table1").Get(ctx, "row1", &value); err != nil {
-		t.Fatalf("table1.Get() failed: %v", err)
+	if err := dbHandle2.Collection("collection1").Get(ctx, "row1", &value); err != nil {
+		t.Fatalf("collection1.Get() failed: %v", err)
 	}
 }
 
diff --git a/syncbase/syncgroup_test.go b/syncbase/syncgroup_test.go
index eb22fe4..81b5954 100644
--- a/syncbase/syncgroup_test.go
+++ b/syncbase/syncgroup_test.go
@@ -37,7 +37,7 @@
 
 	// Prefill entries before creating a syncgroup to exercise the bootstrap
 	// of a syncgroup through Snapshot operations to the watcher.
-	t1 := tu.CreateTable(t, ctx, d, "t1")
+	t1 := tu.CreateCollection(t, ctx, d, "t1")
 	for _, k := range []string{"foo123", "foobar123", "xyz"} {
 		if err := t1.Put(ctx, k, "value@"+k); err != nil {
 			t.Fatalf("t1.Put() of %s failed: %v", k, err)
@@ -45,11 +45,11 @@
 	}
 
 	// Create successfully.
-	// TODO(rdaoud): switch prefixes to (table, prefix) tuples.
+	// TODO(rdaoud): switch prefixes to (collection, prefix) tuples.
 	spec = wire.SyncgroupSpec{
 		Description: "test syncgroup sg1",
 		Perms:       nil,
-		Prefixes:    []wire.TableRow{{TableName: "t1", Row: "foo"}},
+		Prefixes:    []wire.CollectionRow{{CollectionName: "t1", Row: "foo"}},
 	}
 	createSyncgroup(t, ctx, d, sg1, spec, verror.ID(""))
 
@@ -73,7 +73,7 @@
 
 	// Create a nested syncgroup.
 	spec.Description = "test syncgroup sg3"
-	spec.Prefixes = []wire.TableRow{{TableName: "t1", Row: "foobar"}}
+	spec.Prefixes = []wire.CollectionRow{{CollectionName: "t1", Row: "foobar"}}
 	sg3 := naming.Join(sName, common.SyncbaseSuffix, "sg3")
 	createSyncgroup(t, ctx, d, sg3, spec, verror.ID(""))
 
@@ -106,7 +106,7 @@
 	specA := wire.SyncgroupSpec{
 		Description: "test syncgroup sgA",
 		Perms:       perms("root:client1"),
-		Prefixes:    []wire.TableRow{{TableName: "t1", Row: "foo"}},
+		Prefixes:    []wire.CollectionRow{{CollectionName: "t1", Row: "foo"}},
 	}
 	sgNameA := naming.Join(sName, common.SyncbaseSuffix, "sgA")
 	createSyncgroup(t, ctx1, d1, sgNameA, specA, verror.ID(""))
@@ -141,7 +141,7 @@
 	specB := wire.SyncgroupSpec{
 		Description: "test syncgroup sgB",
 		Perms:       perms("root:client1", "root:client2"),
-		Prefixes:    []wire.TableRow{{TableName: "t1", Row: "foo"}},
+		Prefixes:    []wire.CollectionRow{{CollectionName: "t1", Row: "foo"}},
 	}
 	sgNameB := naming.Join(sName, common.SyncbaseSuffix, "sgB")
 	createSyncgroup(t, ctx1, d1, sgNameB, specB, verror.ID(""))
@@ -170,7 +170,7 @@
 	spec := wire.SyncgroupSpec{
 		Description: "test syncgroup sg1",
 		Perms:       perms("root:client"),
-		Prefixes:    []wire.TableRow{{TableName: "t1", Row: "foo"}},
+		Prefixes:    []wire.CollectionRow{{CollectionName: "t1", Row: "foo"}},
 	}
 	createSyncgroup(t, ctx, d, sgName, spec, verror.ID(""))
 
diff --git a/syncbase/syncgroup_v23_test.go b/syncbase/syncgroup_v23_test.go
index 3c6fa9a..5df83b9 100644
--- a/syncbase/syncgroup_v23_test.go
+++ b/syncbase/syncgroup_v23_test.go
@@ -30,7 +30,7 @@
 )
 
 const (
-	testTable = "tb"
+	testCollection = "c"
 )
 
 // NOTE(sadovsky): These tests take a very long time to run - nearly 4 minutes
@@ -60,7 +60,7 @@
 	sgName := naming.Join("sync0", common.SyncbaseSuffix, "SG1")
 
 	ok(t, runSetupAppA(client0Ctx, "sync0"))
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "tb:foo", "", "root:s0", "root:s1"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "c:foo", "", "root:s0", "root:s1"))
 
 	ok(t, runSetupAppA(client1Ctx, "sync1"))
 	ok(t, runJoinSyncgroup(client1Ctx, "sync1", sgName))
@@ -90,7 +90,7 @@
 	sgName := naming.Join("sync0", common.SyncbaseSuffix, "SG1")
 
 	ok(t, runSetupAppA(client0Ctx, "sync0"))
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "tb:foo,tb:bar", "", "root:s0", "root:s1"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "c:foo,c:bar", "", "root:s0", "root:s1"))
 	ok(t, runPopulateData(client0Ctx, "sync0", "foo", 0))
 	ok(t, runPopulateNonVomData(client0Ctx, "sync0", "bar", 0))
 
@@ -130,7 +130,7 @@
 	sgName := naming.Join("sync0", common.SyncbaseSuffix, "SG1")
 
 	ok(t, runSetupAppA(client0Ctx, "sync0"))
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "tb:foo,tb:bar", "", "root:s0", "root:s1"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "c:foo,c:bar", "", "root:s0", "root:s1"))
 	ok(t, runPopulateData(client0Ctx, "sync0", "foo", 0))
 
 	ok(t, runSetupAppA(client1Ctx, "sync1"))
@@ -181,7 +181,7 @@
 	sgName := naming.Join("sync0", common.SyncbaseSuffix, "SG1")
 
 	ok(t, runSetupAppA(client0Ctx, "sync0"))
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "tb:foo", "", "root:s0", "root:s1"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "c:foo", "", "root:s0", "root:s1"))
 	ok(t, runPopulateData(client0Ctx, "sync0", "foo", 0))
 
 	// This is a decoy syncgroup that no other Syncbase joins, but is on the
@@ -191,7 +191,7 @@
 	// syncgroup. This triggers the handling of filtered log records in the
 	// restartability code.
 	sgName1 := naming.Join("sync0", common.SyncbaseSuffix, "SG2")
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName1, "tb:bar", "", "root:s0", "root:s1"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName1, "c:bar", "", "root:s0", "root:s1"))
 	ok(t, runPopulateData(client0Ctx, "sync0", "bar", 0))
 
 	ok(t, runSetupAppA(client1Ctx, "sync1"))
@@ -205,15 +205,15 @@
 	cleanSync0 = sh.StartSyncbase(server0Creds, syncbaselib.Opts{Name: "sync0", RootDir: server0RDir}, `{"Read": {"In":["root:c0"]}, "Write": {"In":["root:c0"]}}`)
 	cleanSync1 = sh.StartSyncbase(server1Creds, syncbaselib.Opts{Name: "sync1", RootDir: server1RDir}, `{"Read": {"In":["root:c1"]}, "Write": {"In":["root:c1"]}}`)
 
-	ok(t, runSetSyncgroupSpec(client0Ctx, "sync0", sgName, "v2", "tb:foo", "root:s0", "root:s1", "root:s3"))
-	ok(t, runGetSyncgroupSpec(client1Ctx, "sync1", sgName, "v2", "tb:foo", "root:s0", "root:s1", "root:s3"))
+	ok(t, runSetSyncgroupSpec(client0Ctx, "sync0", sgName, "v2", "c:foo", "root:s0", "root:s1", "root:s3"))
+	ok(t, runGetSyncgroupSpec(client1Ctx, "sync1", sgName, "v2", "c:foo", "root:s0", "root:s1", "root:s3"))
 
 	ok(t, runUpdateData(client1Ctx, "sync1", 5))
 	ok(t, runPopulateData(client1Ctx, "sync1", "foo", 10))
-	ok(t, runSetSyncgroupSpec(client1Ctx, "sync1", sgName, "v3", "tb:foo", "root:s0", "root:s1", "root:s4"))
+	ok(t, runSetSyncgroupSpec(client1Ctx, "sync1", sgName, "v3", "c:foo", "root:s0", "root:s1", "root:s4"))
 
 	ok(t, runVerifyLocalAndRemoteData(client0Ctx, "sync0"))
-	ok(t, runGetSyncgroupSpec(client0Ctx, "sync0", sgName, "v3", "tb:foo", "root:s0", "root:s1", "root:s4"))
+	ok(t, runGetSyncgroupSpec(client0Ctx, "sync0", sgName, "v3", "c:foo", "root:s0", "root:s1", "root:s4"))
 
 	// Shutdown and restart Syncbase instances.
 	cleanSync0(os.Interrupt)
@@ -222,8 +222,8 @@
 	_ = sh.StartSyncbase(server0Creds, syncbaselib.Opts{Name: "sync0", RootDir: server0RDir}, `{"Read": {"In":["root:c0"]}, "Write": {"In":["root:c0"]}}`)
 	_ = sh.StartSyncbase(server1Creds, syncbaselib.Opts{Name: "sync1", RootDir: server1RDir}, `{"Read": {"In":["root:c1"]}, "Write": {"In":["root:c1"]}}`)
 
-	ok(t, runGetSyncgroupSpec(client0Ctx, "sync0", sgName, "v3", "tb:foo", "root:s0", "root:s1", "root:s4"))
-	ok(t, runGetSyncgroupSpec(client1Ctx, "sync1", sgName, "v3", "tb:foo", "root:s0", "root:s1", "root:s4"))
+	ok(t, runGetSyncgroupSpec(client0Ctx, "sync0", sgName, "v3", "c:foo", "root:s0", "root:s1", "root:s4"))
+	ok(t, runGetSyncgroupSpec(client1Ctx, "sync1", sgName, "v3", "c:foo", "root:s0", "root:s1", "root:s4"))
 	ok(t, runPopulateData(client0Ctx, "sync0", "foo", 20))
 	ok(t, runVerifySyncgroupData(client1Ctx, "sync1", "foo", 20, 10, true))
 }
@@ -253,7 +253,7 @@
 	sgName := naming.Join("sync0", common.SyncbaseSuffix, "SG1")
 
 	ok(t, runSetupAppA(client0Ctx, "sync0"))
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "tb:foo", "", "root:s0", "root:s1"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "c:foo", "", "root:s0", "root:s1"))
 	ok(t, runPopulateData(client0Ctx, "sync0", "foobarbaz", 0))
 	ok(t, runPopulateData(client0Ctx, "sync0", "foo", 0))
 	ok(t, runSetPrefixPermissions(client0Ctx, "sync0", "foo", "root:c0", "root:c1"))
@@ -320,7 +320,7 @@
 	sgName := naming.Join("sync0", common.SyncbaseSuffix, "SG1")
 
 	ok(t, runSetupAppA(client0Ctx, "sync0"))
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "tb:foo", "", "root:s0", "root:s1"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "c:foo", "", "root:s0", "root:s1"))
 	ok(t, runPopulateData(client0Ctx, "sync0", "foo", 0))
 
 	ok(t, runSetupAppA(client1Ctx, "sync1"))
@@ -363,8 +363,8 @@
 	sg2Name := naming.Join("sync0", common.SyncbaseSuffix, "SG2")
 
 	ok(t, runSetupAppA(client0Ctx, "sync0"))
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sg1Name, "tb:foo", "", "root:s0", "root:s1"))
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sg2Name, "tb:f", "", "root:s0", "root:s1"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sg1Name, "c:foo", "", "root:s0", "root:s1"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sg2Name, "c:f", "", "root:s0", "root:s1"))
 	ok(t, runPopulateData(client0Ctx, "sync0", "f", 0))
 	ok(t, runPopulateData(client0Ctx, "sync0", "foo", 0))
 
@@ -407,15 +407,15 @@
 	sg3Name := naming.Join("sync1", common.SyncbaseSuffix, "SG3")
 
 	ok(t, runSetupAppA(client0Ctx, "sync0"))
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sg1Name, "tb:foo", "", "root:s0", "root:s1", "root:s2"))
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sg2Name, "tb:f", "", "root:s0", "root:s2"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sg1Name, "c:foo", "", "root:s0", "root:s1", "root:s2"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sg2Name, "c:f", "", "root:s0", "root:s2"))
 	ok(t, runPopulateData(client0Ctx, "sync0", "f", 0))
 	ok(t, runPopulateData(client0Ctx, "sync0", "foo", 0))
 
 	ok(t, runSetupAppA(client1Ctx, "sync1"))
 	ok(t, runJoinSyncgroup(client1Ctx, "sync1", sg1Name))
 	ok(t, runVerifySyncgroupData(client1Ctx, "sync1", "foo", 0, 10, false))
-	ok(t, runCreateSyncgroup(client1Ctx, "sync1", sg3Name, "tb:f", "", "root:s1", "root:s2"))
+	ok(t, runCreateSyncgroup(client1Ctx, "sync1", sg3Name, "c:f", "", "root:s1", "root:s2"))
 
 	ok(t, runSetupAppA(client2Ctx, "sync2"))
 	ok(t, runJoinSyncgroup(client2Ctx, "sync2", sg2Name))
@@ -446,12 +446,12 @@
 
 	sgName := naming.Join("sync0", common.SyncbaseSuffix, "SG1")
 
-	// Populate table data before creating the syncgroup.  Also populate
+	// Populate collection data before creating the syncgroup.  Also populate
 	// with data that is not part of the syncgroup to verify filtering.
 	ok(t, runSetupAppA(client0Ctx, "sync0"))
 	ok(t, runPopulateData(client0Ctx, "sync0", "foo", 0))
 	ok(t, runPopulateData(client0Ctx, "sync0", "bar", 0))
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "tb:foo", "", "root:s0", "root:s1"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "c:foo", "", "root:s0", "root:s1"))
 
 	ok(t, runSetupAppA(client1Ctx, "sync1"))
 	ok(t, runJoinSyncgroup(client1Ctx, "sync1", sgName))
@@ -461,9 +461,9 @@
 
 // TestV23SyncbasedGetDeltasMultiApp tests the sending of deltas between two
 // Syncbase instances and their clients across multiple apps, databases, and
-// tables.  The 1st client puts entries in multiple tables across multiple
-// app databases then creates multiple syncgroups (one per database) over that
-// data.  The 2nd client joins these syncgroups and reads all the data.
+// collections. The 1st client puts entries in multiple collections across
+// multiple app databases then creates multiple syncgroups (one per database)
+// over that data. The 2nd client joins these syncgroups and reads all the data.
 func TestV23SyncbasedGetDeltasMultiApp(t *testing.T) {
 	v23test.SkipUnlessRunningIntegrationTests(t)
 	sh := v23test.NewShell(t, nil)
@@ -479,7 +479,7 @@
 	sh.StartSyncbase(server1Creds, syncbaselib.Opts{Name: "sync1"}, `{"Read": {"In":["root:c1"]}, "Write": {"In":["root:c1"]}}`)
 
 	sgNamePrefix := naming.Join("sync0", common.SyncbaseSuffix)
-	na, nd, nt := 2, 2, 2 // number of apps, dbs, tables
+	na, nd, nt := 2, 2, 2 // number of apps, dbs, collections
 
 	ok(t, runSetupAppMulti(client0Ctx, "sync0", na, nd, nt))
 	ok(t, runPopulateSyncgroupMulti(client0Ctx, "sync0", sgNamePrefix, na, nd, nt, "foo", "bar"))
@@ -514,7 +514,7 @@
 	sgName := naming.Join("sync0", common.SyncbaseSuffix, "SG1")
 
 	ok(t, runSetupAppA(client0Ctx, "sync0"))
-	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "tb:foo", "", "root:s0", "root:s1", "root:s2"))
+	ok(t, runCreateSyncgroup(client0Ctx, "sync0", sgName, "c:foo", "", "root:s0", "root:s1", "root:s2"))
 	ok(t, runPopulateData(client0Ctx, "sync0", "foo", 0))
 
 	ok(t, runSetupAppA(client1Ctx, "sync1"))
@@ -534,16 +534,16 @@
 // Helpers.
 
 // toSgPrefixes converts, for example, "a:b,c:" to
-// [{TableName: "a", Row: "b"}, {TableName: "c", Row: ""}].
-func toSgPrefixes(csv string) []wire.TableRow {
+// [{CollectionName: "a", Row: "b"}, {CollectionName: "c", Row: ""}].
+func toSgPrefixes(csv string) []wire.CollectionRow {
 	strs := strings.Split(csv, ",")
-	res := make([]wire.TableRow, len(strs))
+	res := make([]wire.CollectionRow, len(strs))
 	for i, v := range strs {
 		parts := strings.SplitN(v, ":", 2)
 		if len(parts) != 2 {
 			panic(fmt.Sprintf("invalid prefix string: %q", v))
 		}
-		res[i] = wire.TableRow{TableName: parts[0], Row: parts[1]}
+		res[i] = wire.CollectionRow{CollectionName: parts[0], Row: parts[1]}
 	}
 	return res
 }
@@ -560,8 +560,8 @@
 	if err := d.Create(ctx, nil); err != nil {
 		return err
 	}
-	tb := d.Table(testTable)
-	if err := tb.Create(ctx, nil); err != nil {
+	c := d.Collection(testCollection)
+	if err := c.Create(ctx, nil); err != nil {
 		return err
 	}
 
@@ -680,11 +680,11 @@
 	d := a.Database("d", nil)
 
 	// Do Puts.
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	for i := start; i < start+10; i++ {
 		key := fmt.Sprintf("%s%d", keyPrefix, i)
-		r := tb.Row(key)
+		r := c.Row(key)
 		if err := r.Put(ctx, "testkey"+key); err != nil {
 			return fmt.Errorf("r.Put() failed: %v\n", err)
 		}
@@ -697,15 +697,15 @@
 	d := a.Database("d", nil)
 
 	// Do Puts.
-	tb := d.Table("tb")
+	c := d.Collection("c")
 
 	for i := start; i < start+10; i++ {
 		key := fmt.Sprintf("%s%d", keyPrefix, i)
-		r := tb.Row(key)
-		c := wire.RowClient(r.FullName())
+		r := c.Row(key)
+		rc := wire.RowClient(r.FullName())
 		val := []byte("nonvomtestkey" + key)
-		if err := c.Put(ctx, -1, val); err != nil {
-			return fmt.Errorf("c.Put() failed: %v\n", err)
+		if err := rc.Put(ctx, -1, val); err != nil {
+			return fmt.Errorf("rc.Put() failed: %v\n", err)
 		}
 	}
 	return nil
@@ -716,11 +716,11 @@
 	d := a.Database("d", nil)
 
 	// Do Puts.
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	for i := start; i < start+5; i++ {
 		key := fmt.Sprintf("foo%d", i)
-		r := tb.Row(key)
+		r := c.Row(key)
 		if err := r.Put(ctx, "testkey"+serviceName+key); err != nil {
 			return fmt.Errorf("r.Put() failed: %v\n", err)
 		}
@@ -734,11 +734,11 @@
 	d := a.Database("d", nil)
 
 	// Do Puts.
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	for i := start; i < start+5; i++ {
 		key := fmt.Sprintf("foo%d", i)
-		r := tb.Row(key)
+		r := c.Row(key)
 		if err := r.Delete(ctx); err != nil {
 			return fmt.Errorf("r.Delete() failed: %v\n", err)
 		}
@@ -752,10 +752,10 @@
 	d := a.Database("d", nil)
 
 	// Set acl.
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
-	if err := tb.SetPrefixPermissions(ctx, syncbase.Prefix(keyPrefix), perms(aclBlessings...)); err != nil {
-		return fmt.Errorf("tb.SetPrefixPermissions() failed: %v\n", err)
+	if err := c.SetPrefixPermissions(ctx, syncbase.Prefix(keyPrefix), perms(aclBlessings...)); err != nil {
+		return fmt.Errorf("c.SetPrefixPermissions() failed: %v\n", err)
 	}
 
 	return nil
@@ -766,11 +766,11 @@
 	d := a.Database("d", nil)
 
 	// Wait for a bit (up to 4 sec) until the last key appears.
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	lastKey := fmt.Sprintf("%s%d", keyPrefix, start+count-1)
 
-	r := tb.Row(lastKey)
+	r := c.Row(lastKey)
 	for i := 0; i < 8; i++ {
 		time.Sleep(500 * time.Millisecond)
 		var value string
@@ -782,7 +782,7 @@
 	// Verify that all keys and values made it correctly.
 	for i := start; i < start+count; i++ {
 		key := fmt.Sprintf("%s%d", keyPrefix, i)
-		r := tb.Row(key)
+		r := c.Row(key)
 		var got string
 		if err := r.Get(ctx, &got); err != nil {
 			return fmt.Errorf("r.Get() failed: %v\n", err)
@@ -795,7 +795,7 @@
 
 	if !skipScan {
 		// Re-verify using a scan operation.
-		stream := tb.Scan(ctx, syncbase.Prefix(keyPrefix))
+		stream := c.Scan(ctx, syncbase.Prefix(keyPrefix))
 		for i := 0; stream.Advance(); i++ {
 			want := fmt.Sprintf("%s%d", keyPrefix, i)
 			got := stream.Key()
@@ -827,7 +827,7 @@
 	ctxWithTimeout, cancel := context.WithTimeout(ctx, 10*time.Second)
 	defer cancel()
 
-	stream, err := d.Watch(ctxWithTimeout, testTable, keyPrefix, beforeSyncMarker)
+	stream, err := d.Watch(ctxWithTimeout, testCollection, keyPrefix, beforeSyncMarker)
 	if err != nil {
 		return fmt.Errorf("watch error: %v\n", err)
 	}
@@ -847,8 +847,8 @@
 	}
 
 	for i, change := range changes {
-		if got, want := change.Table, "tb"; got != want {
-			return fmt.Errorf("unexpected watch table: got %q, want %q", got, want)
+		if got, want := change.Collection, "c"; got != want {
+			return fmt.Errorf("unexpected watch collection: got %q, want %q", got, want)
 		}
 		if got, want := change.Row, fmt.Sprintf("%s%d", keyPrefix, i); got != want {
 			return fmt.Errorf("unexpected watch row: got %q, want %q", got, want)
@@ -881,15 +881,15 @@
 	d := a.Database("d", nil)
 
 	// Wait for a bit (up to 4 sec) until the last key appears.
-	tb := d.Table("tb")
+	c := d.Collection("c")
 
 	lastKey := fmt.Sprintf("%s%d", keyPrefix, start+count-1)
 
-	r := tb.Row(lastKey)
-	c := wire.RowClient(r.FullName())
+	r := c.Row(lastKey)
+	rc := wire.RowClient(r.FullName())
 	for i := 0; i < 8; i++ {
 		time.Sleep(500 * time.Millisecond)
-		if _, err := c.Get(ctx, -1); err == nil {
+		if _, err := rc.Get(ctx, -1); err == nil {
 			break
 		}
 	}
@@ -897,12 +897,12 @@
 	// Verify that all keys and values made it correctly.
 	for i := start; i < start+count; i++ {
 		key := fmt.Sprintf("%s%d", keyPrefix, i)
-		r := tb.Row(key)
-		c := wire.RowClient(r.FullName())
+		r := c.Row(key)
+		rc := wire.RowClient(r.FullName())
 		var got string
-		val, err := c.Get(ctx, -1)
+		val, err := rc.Get(ctx, -1)
 		if err != nil {
-			return fmt.Errorf("c.Get() failed: %v\n", err)
+			return fmt.Errorf("rc.Get() failed: %v\n", err)
 		}
 		got = string(val)
 		want := "nonvomtestkey" + key
@@ -918,9 +918,9 @@
 	d := a.Database("d", nil)
 
 	// Wait for a bit for deletions to propagate.
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
-	r := tb.Row("foo4")
+	r := c.Row("foo4")
 	for i := 0; i < 8; i++ {
 		time.Sleep(500 * time.Millisecond)
 		var value string
@@ -930,7 +930,7 @@
 	}
 
 	// Verify using a scan operation.
-	stream := tb.Scan(ctx, syncbase.Prefix(keyPrefix))
+	stream := c.Scan(ctx, syncbase.Prefix(keyPrefix))
 	count := 0
 	for i := 5; stream.Advance(); i++ {
 		want := fmt.Sprintf("%s%d", keyPrefix, i)
@@ -962,7 +962,7 @@
 func runVerifyConflictResolution(ctx *context.T, serviceName string) error {
 	a := syncbase.NewService(serviceName).App("a")
 	d := a.Database("d", nil)
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	wantData := []struct {
 		start  uint64
@@ -977,7 +977,7 @@
 	for _, d := range wantData {
 		for i := d.start; i < d.start+d.count; i++ {
 			key := fmt.Sprintf("foo%d", i)
-			r := tb.Row(key)
+			r := c.Row(key)
 			var got string
 			if err := r.Get(ctx, &got); err != nil {
 				return fmt.Errorf("r.Get() failed: %v\n", err)
@@ -1000,11 +1000,11 @@
 func runVerifyNonSyncgroupData(ctx *context.T, serviceName, keyPrefix string) error {
 	a := syncbase.NewService(serviceName).App("a")
 	d := a.Database("d", nil)
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	// Verify through a scan that none of that data exists.
 	count := 0
-	stream := tb.Scan(ctx, syncbase.Prefix(keyPrefix))
+	stream := c.Scan(ctx, syncbase.Prefix(keyPrefix))
 	for stream.Advance() {
 		count++
 	}
@@ -1022,10 +1022,10 @@
 func runVerifyLocalAndRemoteData(ctx *context.T, serviceName string) error {
 	a := syncbase.NewService(serviceName).App("a")
 	d := a.Database("d", nil)
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	// Wait for a bit (up to 4 sec) until the last key appears.
-	r := tb.Row("foo19")
+	r := c.Row("foo19")
 	for i := 0; i < 8; i++ {
 		time.Sleep(500 * time.Millisecond)
 		var value string
@@ -1048,7 +1048,7 @@
 	for _, d := range wantData {
 		for i := d.start; i < d.start+d.count; i++ {
 			key := fmt.Sprintf("foo%d", i)
-			r := tb.Row(key)
+			r := c.Row(key)
 			var got string
 			if err := r.Get(ctx, &got); err != nil {
 				return fmt.Errorf("r.Get() failed: %v\n", err)
@@ -1067,11 +1067,11 @@
 	d := a.Database("d", nil)
 
 	// Wait for a bit (up to 4 sec) until the last key disappears.
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
 	lastKey := fmt.Sprintf("%s%d", keyPrefix, start+count-1)
 
-	r := tb.Row(lastKey)
+	r := c.Row(lastKey)
 	for i := 0; i < 8; i++ {
 		time.Sleep(500 * time.Millisecond)
 		var value string
@@ -1083,7 +1083,7 @@
 	// Verify that all keys and values have lost access.
 	for i := start; i < start+count; i++ {
 		key := fmt.Sprintf("%s%d", keyPrefix, i)
-		r := tb.Row(key)
+		r := c.Row(key)
 		var got string
 		if err := r.Get(ctx, &got); verror.ErrorID(err) != verror.ErrNoAccess.ID {
 			return fmt.Errorf("r.Get() didn't fail: %v\n", err)
@@ -1105,9 +1105,9 @@
 	// conditions. Note that we wait longer than the 2 node tests since more
 	// nodes implies more pair-wise communication before achieving steady
 	// state.
-	tb := d.Table(testTable)
+	c := d.Collection(testCollection)
 
-	r := tb.Row("f9")
+	r := c.Row("f9")
 	for i := 0; i < 8; i++ {
 		time.Sleep(1 * time.Second)
 		var value string
@@ -1121,7 +1121,7 @@
 	for _, p := range pfxs {
 		for i := 0; i < 10; i++ {
 			key := fmt.Sprintf("%s%d", p, i)
-			r := tb.Row(key)
+			r := c.Row(key)
 			var got string
 			if err := r.Get(ctx, &got); err != nil {
 				return fmt.Errorf("r.Get() failed: %v\n", err)
@@ -1149,8 +1149,8 @@
 			d.Create(ctx, nil)
 
 			for k := 0; k < numTbs; k++ {
-				tbName := fmt.Sprintf("tb%d", k)
-				d.Table(tbName).Create(ctx, nil)
+				cName := fmt.Sprintf("c%d", k)
+				d.Collection(cName).Create(ctx, nil)
 			}
 		}
 	}
@@ -1173,20 +1173,20 @@
 			dbName := fmt.Sprintf("d%d", j)
 			d := a.Database(dbName, nil)
 
-			// For each table, pre-populate entries on each prefix.
+			// For each collection, pre-populate entries on each prefix.
 			// Also determine the syncgroup prefixes.
 			var sgPrefixes []string
 			for k := 0; k < numTbs; k++ {
-				tbName := fmt.Sprintf("tb%d", k)
-				tb := d.Table(tbName)
+				cName := fmt.Sprintf("c%d", k)
+				c := d.Collection(cName)
 
 				for _, pfx := range prefixes {
-					p := fmt.Sprintf("%s:%s", tbName, pfx)
+					p := fmt.Sprintf("%s:%s", cName, pfx)
 					sgPrefixes = append(sgPrefixes, p)
 
 					for n := 0; n < 10; n++ {
 						key := fmt.Sprintf("%s%d", pfx, n)
-						r := tb.Row(key)
+						r := c.Row(key)
 						if err := r.Put(ctx, "testkey"+key); err != nil {
 							return fmt.Errorf("r.Put() failed: %v\n", err)
 						}
@@ -1194,7 +1194,7 @@
 				}
 			}
 
-			// Create one syncgroup per database across all tables
+			// Create one syncgroup per database across all collections
 			// and prefixes.
 			sgName := naming.Join(sgNamePrefix, appName, dbName)
 			spec := wire.SyncgroupSpec{
@@ -1252,13 +1252,13 @@
 			d := a.Database(dbName, nil)
 
 			for k := 0; k < numTbs; k++ {
-				tbName := fmt.Sprintf("tb%d", k)
-				tb := d.Table(tbName)
+				cName := fmt.Sprintf("c%d", k)
+				c := d.Collection(cName)
 
 				for _, pfx := range prefixes {
 					for n := 0; n < 10; n++ {
 						key := fmt.Sprintf("%s%d", pfx, n)
-						r := tb.Row(key)
+						r := c.Row(key)
 						var got string
 						if err := r.Get(ctx, &got); err != nil {
 							return fmt.Errorf("r.Get() failed: %v\n", err)
diff --git a/syncbase/table.go b/syncbase/table.go
deleted file mode 100644
index f7ee840..0000000
--- a/syncbase/table.go
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2015 The Vanadium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syncbase
-
-import (
-	"v.io/v23/context"
-	"v.io/v23/naming"
-	"v.io/v23/security/access"
-	wire "v.io/v23/services/syncbase"
-	"v.io/v23/syncbase/util"
-)
-
-func newTable(parentFullName, relativeName string, schemaVersion int32) Table {
-	// Escape relativeName so that any forward slashes get dropped, thus ensuring
-	// that the server will interpret fullName as referring to a table object.
-	// Note that the server will still reject this name if util.ValidTableName
-	// returns false.
-	fullName := naming.Join(parentFullName, util.Escape(relativeName))
-	return &table{
-		c:               wire.TableClient(fullName),
-		fullName:        fullName,
-		name:            relativeName,
-		dbSchemaVersion: schemaVersion,
-	}
-}
-
-type table struct {
-	c               wire.TableClientMethods
-	fullName        string
-	name            string
-	dbSchemaVersion int32
-}
-
-var _ Table = (*table)(nil)
-
-// Name implements Table.Name.
-func (t *table) Name() string {
-	return t.name
-}
-
-// FullName implements Table.FullName.
-func (t *table) FullName() string {
-	return t.fullName
-}
-
-// Exists implements Table.Exists.
-func (t *table) Exists(ctx *context.T) (bool, error) {
-	return t.c.Exists(ctx, t.dbSchemaVersion)
-}
-
-// Create implements Table.Create.
-func (t *table) Create(ctx *context.T, perms access.Permissions) error {
-	return t.c.Create(ctx, t.dbSchemaVersion, perms)
-}
-
-// Destroy implements Table.Destroy.
-func (t *table) Destroy(ctx *context.T) error {
-	return t.c.Destroy(ctx, t.dbSchemaVersion)
-}
-
-// GetPermissions implements Table.GetPermissions.
-func (t *table) GetPermissions(ctx *context.T) (access.Permissions, error) {
-	return t.c.GetPermissions(ctx, t.dbSchemaVersion)
-}
-
-// SetPermissions implements Table.SetPermissions.
-func (t *table) SetPermissions(ctx *context.T, perms access.Permissions) error {
-	return t.c.SetPermissions(ctx, t.dbSchemaVersion, perms)
-}
-
-// Row implements Table.Row.
-func (t *table) Row(key string) Row {
-	return newRow(t.fullName, key, t.dbSchemaVersion)
-}
-
-// Get implements Table.Get.
-func (t *table) Get(ctx *context.T, key string, value interface{}) error {
-	return t.Row(key).Get(ctx, value)
-}
-
-// Put implements Table.Put.
-func (t *table) Put(ctx *context.T, key string, value interface{}) error {
-	return t.Row(key).Put(ctx, value)
-}
-
-// Delete implements Table.Delete.
-func (t *table) Delete(ctx *context.T, key string) error {
-	return t.Row(key).Delete(ctx)
-}
-
-// DeleteRange implements Table.DeleteRange.
-func (t *table) DeleteRange(ctx *context.T, r RowRange) error {
-	return t.c.DeleteRange(ctx, t.dbSchemaVersion, []byte(r.Start()), []byte(r.Limit()))
-}
-
-// Scan implements Table.Scan.
-func (t *table) Scan(ctx *context.T, r RowRange) ScanStream {
-	ctx, cancel := context.WithCancel(ctx)
-	call, err := t.c.Scan(ctx, t.dbSchemaVersion, []byte(r.Start()), []byte(r.Limit()))
-	if err != nil {
-		return &InvalidScanStream{Error: err}
-	}
-	return newScanStream(cancel, call)
-}
-
-// GetPrefixPermissions implements Table.GetPrefixPermissions.
-func (t *table) GetPrefixPermissions(ctx *context.T, key string) ([]PrefixPermissions, error) {
-	wirePermsList, err := t.c.GetPrefixPermissions(ctx, t.dbSchemaVersion, key)
-	permsList := []PrefixPermissions{}
-	for _, v := range wirePermsList {
-		permsList = append(permsList, PrefixPermissions{Prefix: Prefix(v.Prefix), Perms: v.Perms})
-	}
-	return permsList, err
-}
-
-// SetPrefixPermissions implements Table.SetPrefixPermissions.
-func (t *table) SetPrefixPermissions(ctx *context.T, prefix PrefixRange, perms access.Permissions) error {
-	return t.c.SetPrefixPermissions(ctx, t.dbSchemaVersion, prefix.Prefix(), perms)
-}
-
-// DeletePrefixPermissions implements Table.DeletePrefixPermissions.
-func (t *table) DeletePrefixPermissions(ctx *context.T, prefix PrefixRange) error {
-	return t.c.DeletePrefixPermissions(ctx, t.dbSchemaVersion, prefix.Prefix())
-}
diff --git a/syncbase/util/.api b/syncbase/util/.api
index d250b90..60fcfe5 100644
--- a/syncbase/util/.api
+++ b/syncbase/util/.api
@@ -1,14 +1,14 @@
 pkg util, func Escape(string) string
 pkg util, func IsPrefix(string, string) bool
 pkg util, func ListChildren(*context.T, string) ([]string, error)
-pkg util, func ParseTableRowPair(*context.T, string) (string, string, error)
+pkg util, func ParseCollectionRowPair(*context.T, string) (string, string, error)
 pkg util, func PrefixRangeLimit(string) string
 pkg util, func PrefixRangeStart(string) string
 pkg util, func Unescape(string) (string, bool)
 pkg util, func ValidAppName(string) bool
+pkg util, func ValidCollectionName(string) bool
 pkg util, func ValidDatabaseName(string) bool
 pkg util, func ValidRowKey(string) bool
-pkg util, func ValidTableName(string) bool
 pkg util, type AccessController interface { GetPermissions, SetPermissions }
 pkg util, type AccessController interface, GetPermissions(*context.T) (access.Permissions, string, error)
 pkg util, type AccessController interface, SetPermissions(*context.T, access.Permissions, string) error
diff --git a/syncbase/util/util.go b/syncbase/util/util.go
index 7a61c2d..5692ab0 100644
--- a/syncbase/util/util.go
+++ b/syncbase/util/util.go
@@ -51,7 +51,7 @@
 	return identifierRegexp.MatchString(s)
 }
 
-// maxNameLen is the max allowed number of bytes in app, db, and table names.
+// maxNameLen is the max allowed number of bytes in app, db, and collection names.
 const maxNameLen = 64
 
 // ValidAppName returns true iff the given string is a valid app name.
@@ -70,8 +70,8 @@
 	return validIdentifier(s)
 }
 
-// ValidTableName returns true iff the given string is a valid table name.
-func ValidTableName(s string) bool {
+// ValidCollectionName returns true iff the given string is a valid collection name.
+func ValidCollectionName(s string) bool {
 	if len([]byte(s)) > maxNameLen {
 		return false
 	}
@@ -83,21 +83,21 @@
 	return s != "" && !containsReservedByte(s)
 }
 
-// ParseTableRowPair splits the "<table>/<row>" part of a Syncbase object name
-// into the table name and the row key or prefix.
-func ParseTableRowPair(ctx *context.T, pattern string) (string, string, error) {
+// ParseCollectionRowPair splits the "<collection>/<row>" part of a Syncbase
+// object name into the collection name and the row key or prefix.
+func ParseCollectionRowPair(ctx *context.T, pattern string) (string, string, error) {
 	parts := strings.SplitN(pattern, "/", 2)
-	if len(parts) != 2 { // require both table and row parts
+	if len(parts) != 2 { // require both collection and row parts
 		return "", "", verror.New(verror.ErrBadArg, ctx, pattern)
 	}
-	table, row := parts[0], parts[1]
-	if !ValidTableName(table) {
-		return "", "", verror.New(wire.ErrInvalidName, ctx, table)
+	collection, row := parts[0], parts[1]
+	if !ValidCollectionName(collection) {
+		return "", "", verror.New(wire.ErrInvalidName, ctx, collection)
 	}
 	if row != "" && !ValidRowKey(row) {
 		return "", "", verror.New(wire.ErrInvalidName, ctx, row)
 	}
-	return table, row, nil
+	return collection, row, nil
 }
 
 // PrefixRangeStart returns the start of the row range for the given prefix.
diff --git a/syncbase/util/util_test.go b/syncbase/util/util_test.go
index 9047ef3..6385aa6 100644
--- a/syncbase/util/util_test.go
+++ b/syncbase/util/util_test.go
@@ -55,19 +55,19 @@
 			t.Errorf("%q should be invalid", s)
 		}
 	}
-	for _, s := range tu.OkDbTableNames {
+	for _, s := range tu.OkDbCollectionNames {
 		if !util.ValidDatabaseName(s) {
 			t.Errorf("%q should be valid", s)
 		}
-		if !util.ValidTableName(s) {
+		if !util.ValidCollectionName(s) {
 			t.Errorf("%q should be valid", s)
 		}
 	}
-	for _, s := range tu.NotOkDbTableNames {
+	for _, s := range tu.NotOkDbCollectionNames {
 		if util.ValidDatabaseName(s) {
 			t.Errorf("%q should be invalid", s)
 		}
-		if util.ValidTableName(s) {
+		if util.ValidCollectionName(s) {
 			t.Errorf("%q should be invalid", s)
 		}
 	}
diff --git a/syncbase/watch_stream.go b/syncbase/watch_stream.go
index 0070fee..f001bbc 100644
--- a/syncbase/watch_stream.go
+++ b/syncbase/watch_stream.go
@@ -95,8 +95,8 @@
 // v.io/v23/services/watch to a Syncbase-specific WatchChange struct as defined
 // in v.io/v23/syncbase.
 func ToWatchChange(c watch.Change) WatchChange {
-	// Parse the table and the row.
-	table, row, err := util.ParseTableRowPair(nil, c.Name)
+	// Parse the collection and the row.
+	collection, row, err := util.ParseCollectionRowPair(nil, c.Name)
 	if err != nil {
 		panic(err)
 	}
@@ -123,7 +123,7 @@
 		panic(fmt.Sprintf("unsupported watch change state: %v", c.State))
 	}
 	return WatchChange{
-		Table:        table,
+		Collection:   collection,
 		Row:          row,
 		ChangeType:   changeType,
 		ValueBytes:   storeChange.Value,