The Namespaces API allows you to easily enable
multitenancy
in your application, simply by selecting a namespace string for each tenant using the
appengine.Namespace
function
.
Setting the current namespace
You can set namespaces using
appengine.Namespace
. This returns a new context that will automatically cause the given namespace to be used by
namespace-enabled APIs
.
Most App Engine developers will use their Google Apps domain as the current namespace. Google Apps lets you deploy your app to any domain that you own, so you can easily use this mechanism to configure different namespaces for different domains. Then, you can use those separate namespaces to segregate data across the domains. For more information about setting multiple domains in the Google Apps dashboard, see Deploying Your Application on Your Google Apps URL .
If you do not specify a value for
namespace
, the namespace is set to an empty string. The
namespace
string is arbitrary, but also limited to a maximum of 100 alphanumeric characters, periods, underscores, and hyphens. More explicitly, namespace strings must match the regular expression
[0-9A-Za-z._-]{0,100}
.
By convention, all namespaces starting with "
_
" (underscore) are reserved for system use. This system namespace rule is not enforced, but you could easily encounter undefined negative consequences if you do not follow it.
Avoiding data leaks
One of the risks commonly associated with multitenant apps is the danger that data will leak across namespaces. Unintended data leaks can arise from many sources, including:
- Using namespaces with App Engine APIs that do not yet support namespaces. For example, Blobstore does not support namespaces. If you use Namespaces with Blobstore , you need to avoid using Blobstore queries for end user requests, or Blobstore keys from untrusted sources.
-
Using an external storage medium (instead of memcache and datastore), via
URL Fetch
or some other mechanism, without providing a compartmentalization scheme for namespaces. - Setting a namespace based on a user's email domain. In most cases, you don't want all email addresses of a domain to access a namespace. Using the email domain also prevents your application from using a namespace until the user is logged in.
Deploying namespaces
The following sections describe how to deploy namespaces with other App Engine tools and APIs.
Creating namespaces on a per user basis
Some applications need to create namespaces on a per-user basis. If you want to compartmentalize data at the user level for logged-in users, consider using
user.Current(c).ID
, which returns a unique, permanent ID for the user. The following code sample demonstrates how to use the Users API for this purpose:
import "appengine"
import "appengine/user"
func namespace(c appengine.Context) appengine.Context {
// assumes the user is logged in.
c, err := appengine.Namespace(c, user.Current(c).ID)
if err != nil {
// ...
}
return c
}
Typically, apps that create namespaces on a per-user basis also provide specific landing pages to different users. In these cases, the application needs to provide a URL scheme dictating which landing page to display to a user.
Using namespaces with the Datastore
By default, the datastore uses the current namespace for datastore requests. The API applies this current namespace to
datastore.Key
objects when they are created. Therefore, you need to be careful if an application stores
Key
objects in serialized forms, since the namespace is preserved in those serializations.
If you are using deserialized
Key
objects, make sure that they behave as intended. Most simple applications that use datastore (
put
/
query
/
get
) without using other storage mechanisms will work as expected by setting the current namespace before calling any datastore API.