Multitenancy
Many database systems provide multi-tenant capabilities. They can contain multiple databases, each with their own access controls. FaunaDB takes this much further by allowing any database to have multiple child databases. This enables an operator to manage a single large FaunaDB cluster, create a few top-level databases, and give full administrative access of those databases to associated teams. Each team is free to create as many databases as they need without requiring operator intervention. As far as the team is concerned, they have their own full FaunaDB cluster.
This page will walk through how multiple databases and child databases are created and maintained. In this example a company is using FaunaDB for customer data as well as internal data.
Create Top Level Databases
First, the operator will need to create a set of top-level databases that can be handed over to individual teams. In the following example we will create a "production" database and an "internal" database using the configured secret.
curl https://db.fauna.com/ \
-u fnACrVRyZhACAOvXOTRzOpg1Qqq5oPHKMfOLgcHQ: \
-d '{
"map": {
"lambda": "name",
"expr": {
"create_database": { "object": { "name": { "var": "name" } } }
}
},
"collection": [ "production", "internal" ]
}'
client.Query(
Map(
Arr("production", "internal"),
name => CreateDatabase(Obj("name", name))));
client.query(
Map(
Arr(Value("production"), Value("internal")),
Lambda(
Value("name"),
CreateDatabase(Obj("name", Var("name"))))));
client.Query(
f.Map(
f.Arr{"production", "internal"},
f.Lambda(
"name",
f.CreateDatabase(f.Obj{"name": f.Var("name")}),
),
),
)
client.query(
Map(
Arr("production", "internal"),
Lambda { name => CreateDatabase(Obj("name" -> name)) }))
client.query(
q.map_expr(
lambda name: q.create_database({"name": name}),
["production", "internal"]
))
$client.query do
map ['production', 'internal'] do |name|
create_database(name: name)
end
end
client.query(
Map(
collection: Arr("production", "internal"),
to: { name in CreateDatabase(Obj("name" => name)) }
)
)
client.query(
q.Map(
["production", "internal"],
function(name) {
return q.CreateDatabase({ name: name });
}));
HTTP/1.1 200 OK
{
"resource": [
{
"ref": { "@ref": "databases/production" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "production"
},
{
"ref": { "@ref": "databases/internal" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "internal"
}
]
}
[
{
"ref": { "@ref": "databases/production" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "production"
},
{
"ref": { "@ref": "databases/internal" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "internal"
}
]
[
{
ref: ref(id = "production", class = ref(id = "databases")),
ts: 1520225711026454,
name: "production"
},
{
ref: ref(id = "internal", class = ref(id = "databases")),
ts: 1520225711026454,
name: "internal"
}
]
[
{
"ref": { "@ref": "databases/production" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "production"
},
{
"ref": { "@ref": "databases/internal" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "internal"
}
]
[
{
"ref": { "@ref": "databases/production" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "production"
},
{
"ref": { "@ref": "databases/internal" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "internal"
}
]
[
{
"ref": { "@ref": "databases/production" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "production"
},
{
"ref": { "@ref": "databases/internal" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "internal"
}
]
[
{
"ref": { "@ref": "databases/production" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "production"
},
{
"ref": { "@ref": "databases/internal" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "internal"
}
]
[
{
"ref": { "@ref": "databases/production" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "production"
},
{
"ref": { "@ref": "databases/internal" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "internal"
}
]
[
{
"ref": { "@ref": "databases/production" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "production"
},
{
"ref": { "@ref": "databases/internal" },
"class": { "@ref": "databases" },
"ts": 1520225711026454,
"name": "internal"
}
]
Next we will create an admin key for each database that can be handed to each team.
curl https://db.fauna.com/ \
-u fnACrVRyZhACAOvXOTRzOpg1Qqq5oPHKMfOLgcHQ: \
-d '{
"map": {
"lambda": "db",
"expr": {
"create_key": {
"object": { "role": "admin", "database": { "var": "db" } }
}
}
},
"collection": [ { "database": "production" }, { "database": "internal" } ]
}'
client.Query(
Map(
Arr(Database("production"), Database("internal")),
db => CreateKey(Obj("role", "admin", "database", db))));
client.query(
Map(
Arr(
Database(Value("production")),
Database(Value("internal"))
),
Lambda(
Value("db"),
CreateKey(
Obj("role", Value("admin"), "database", Var("db"))))));
client.Query(
f.Map(
f.Arr{f.Database("production"), f.Database("internal")},
f.Lambda(
"db",
f.CreateKey(
f.Obj{"role": "admin", "database": f.Var("db")},
),
),
),
)
client.query(
Map(
Arr(Database("production"), Database("internal")),
Lambda { db =>
CreateKey(Obj("role" -> "admin", "database" -> db))
}))
client.query(
q.map_expr(
lambda db: q.create_key({"role": "admin", "database": db}),
[q.database("production"), q.database("internal")]
))
$client.query do
map [database('production'), database('internal')] do |db|
create_key(role: 'admin', database: db)
end
end
client.query(
Map(
collection: Arr(Database("production"), Database("internal")),
to: { db in
CreateKey(
Obj("role" => "admin", "database" => db)
)
}
)
)
client.query(
q.Map(
[q.Database("production"), q.Database("internal")],
function(db) {
return q.CreateKey({ role: "admin", database: db });
}));
HTTP/1.1 200 OK
{
"resource": [
{
"ref": { "@ref": "keys/192903235319628288" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/production" },
"secret": "fnACrVR4cUACAFxeJHGB7yuNakuLhwUDLFHe3ghP",
"hashed_secret": "$2a$05$W96WId0vdaO4ABunz/BXVuuCl0WXVMj1d6lGbwiIahWX/gUyyt/wy"
},
{
"ref": { "@ref": "keys/192903235319629312" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/internal" },
"secret": "fnACrVR4cUAGAMbQBucJV2d-yiDy2mDDlOBWUd6A",
"hashed_secret": "$2a$05$kUDZRHxhgjMtrUFoUk.gT.IN2TTyxW4mdKnqr3KPj0wEzw6qVL4zS"
}
]
}
[
{
"ref": { "@ref": "keys/192903235319628288" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/production" },
"secret": "fnACrVR4cUACAFxeJHGB7yuNakuLhwUDLFHe3ghP",
"hashed_secret": "$2a$05$W96WId0vdaO4ABunz/BXVuuCl0WXVMj1d6lGbwiIahWX/gUyyt/wy"
},
{
"ref": { "@ref": "keys/192903235319629312" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/internal" },
"secret": "fnACrVR4cUAGAMbQBucJV2d-yiDy2mDDlOBWUd6A",
"hashed_secret": "$2a$05$kUDZRHxhgjMtrUFoUk.gT.IN2TTyxW4mdKnqr3KPj0wEzw6qVL4zS"
}
]
[
{
ref: ref(id = "192903235319628288", class = ref(id = "keys")),
ts: 1520225711064091,
role: "admin",
database: ref(id = "production", class = ref(id = "databases")),
secret: "fnAC6ms4DzACAI7Fxc7ZZTZZ8eW3u9CqRAuc6Teu",
hashed_secret: "$2a$05$4AucECSN9fEcpxaEvuYh8eYQUAVwut5QPe/kcDRmnc6X7WXypN0kO"
},
{
ref: ref(id = "192903235319629312", class = ref(id = "keys")),
ts: 1520225711064091,
role: "admin",
atabase: ref(id = "internal", class = ref(id = "databases")),
secret: "fnAC6ms4D3ACAHZ9LjSEO1VzFRKb5Ho9o3_hRMAe",
hashed_secret: "$2a$05$yrMM3CK0zMAhSStnRNZdheamolFrR1.ipdgHCJKWBVudZAgoARhPu"
}
]
[
{
"ref": { "@ref": "keys/192903235319628288" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/production" },
"secret": "fnACrVR4cUACAFxeJHGB7yuNakuLhwUDLFHe3ghP",
"hashed_secret": "$2a$05$W96WId0vdaO4ABunz/BXVuuCl0WXVMj1d6lGbwiIahWX/gUyyt/wy"
},
{
"ref": { "@ref": "keys/192903235319629312" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/internal" },
"secret": "fnACrVR4cUAGAMbQBucJV2d-yiDy2mDDlOBWUd6A",
"hashed_secret": "$2a$05$kUDZRHxhgjMtrUFoUk.gT.IN2TTyxW4mdKnqr3KPj0wEzw6qVL4zS"
}
]
[
{
"ref": { "@ref": "keys/192903235319628288" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/production" },
"secret": "fnACrVR4cUACAFxeJHGB7yuNakuLhwUDLFHe3ghP",
"hashed_secret": "$2a$05$W96WId0vdaO4ABunz/BXVuuCl0WXVMj1d6lGbwiIahWX/gUyyt/wy"
},
{
"ref": { "@ref": "keys/192903235319629312" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/internal" },
"secret": "fnACrVR4cUAGAMbQBucJV2d-yiDy2mDDlOBWUd6A",
"hashed_secret": "$2a$05$kUDZRHxhgjMtrUFoUk.gT.IN2TTyxW4mdKnqr3KPj0wEzw6qVL4zS"
}
]
[
{
"ref": { "@ref": "keys/192903235319628288" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/production" },
"secret": "fnACrVR4cUACAFxeJHGB7yuNakuLhwUDLFHe3ghP",
"hashed_secret": "$2a$05$W96WId0vdaO4ABunz/BXVuuCl0WXVMj1d6lGbwiIahWX/gUyyt/wy"
},
{
"ref": { "@ref": "keys/192903235319629312" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/internal" },
"secret": "fnACrVR4cUAGAMbQBucJV2d-yiDy2mDDlOBWUd6A",
"hashed_secret": "$2a$05$kUDZRHxhgjMtrUFoUk.gT.IN2TTyxW4mdKnqr3KPj0wEzw6qVL4zS"
}
]
[
{
"ref": { "@ref": "keys/192903235319628288" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/production" },
"secret": "fnACrVR4cUACAFxeJHGB7yuNakuLhwUDLFHe3ghP",
"hashed_secret": "$2a$05$W96WId0vdaO4ABunz/BXVuuCl0WXVMj1d6lGbwiIahWX/gUyyt/wy"
},
{
"ref": { "@ref": "keys/192903235319629312" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/internal" },
"secret": "fnACrVR4cUAGAMbQBucJV2d-yiDy2mDDlOBWUd6A",
"hashed_secret": "$2a$05$kUDZRHxhgjMtrUFoUk.gT.IN2TTyxW4mdKnqr3KPj0wEzw6qVL4zS"
}
]
[
{
"ref": { "@ref": "keys/192903235319628288" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/production" },
"secret": "fnACrVR4cUACAFxeJHGB7yuNakuLhwUDLFHe3ghP",
"hashed_secret": "$2a$05$W96WId0vdaO4ABunz/BXVuuCl0WXVMj1d6lGbwiIahWX/gUyyt/wy"
},
{
"ref": { "@ref": "keys/192903235319629312" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/internal" },
"secret": "fnACrVR4cUAGAMbQBucJV2d-yiDy2mDDlOBWUd6A",
"hashed_secret": "$2a$05$kUDZRHxhgjMtrUFoUk.gT.IN2TTyxW4mdKnqr3KPj0wEzw6qVL4zS"
}
]
[
{
"ref": { "@ref": "keys/192903235319628288" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/production" },
"secret": "fnACrVR4cUACAFxeJHGB7yuNakuLhwUDLFHe3ghP",
"hashed_secret": "$2a$05$W96WId0vdaO4ABunz/BXVuuCl0WXVMj1d6lGbwiIahWX/gUyyt/wy"
},
{
"ref": { "@ref": "keys/192903235319629312" },
"class": { "@ref": "keys" },
"ts": 1520225711064091,
"role": "admin",
"database": { "@ref": "databases/internal" },
"secret": "fnACrVR4cUAGAMbQBucJV2d-yiDy2mDDlOBWUd6A",
"hashed_secret": "$2a$05$kUDZRHxhgjMtrUFoUk.gT.IN2TTyxW4mdKnqr3KPj0wEzw6qVL4zS"
}
]
Per-Team Child Databases
Given the new keys, each team can create databases that fit their needs. In this case, production will not create any child databases, but the internal tools team will create a set of databases for the products they create.
curl https://db.fauna.com/ \
-u fnACrVR4cUAGAMbQBucJV2d-yiDy2mDDlOBWUd6A: \
-d '{
"map": {
"lambda": "name",
"expr": {
"create_database": { "object": { "name": { "var": "name" } } }
}
},
"collection": [ "personnel", "bulletin-board" ]
}'
client.Query(
Map(
Arr("personnel", "bulletin-board"),
name => CreateDatabase(Obj("name", name))));
client.query(
Map(
Arr(Value("personnel"), Value("bulletin-board")),
Lambda(
Value("name"),
CreateDatabase(Obj("name", Var("name"))))));
client.Query(
f.Map(
f.Arr{"personnel", "bulletin-board"},
f.Lambda(
"name",
f.CreateDatabase(f.Obj{"name": f.Var("name")}),
),
),
)
client.query(
Map(
Arr("personnel", "bulletin-board"),
Lambda { name => CreateDatabase(Obj("name" -> name)) }))
client.query(
q.map_expr(
lambda name: q.create_database({"name": name}),
["personnel", "bulletin-board"]
))
$client.query do
map ['personnel', 'bulletin-board'] do |name|
create_database(name: name)
end
end
client.query(
Map(
collection: Arr("personnel", "bulletin-board"),
to: { name in CreateDatabase(Obj("name" => name)) }
)
)
client.query(
q.Map(
["personnel", "bulletin-board"],
function(name) {
return q.CreateDatabase({ name: name });
}));
HTTP/1.1 200 OK
{
"resource": [
{
"ref": { "@ref": "databases/personnel" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "personnel"
},
{
"ref": { "@ref": "databases/bulletin-board" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "bulletin-board"
}
]
}
[
{
"ref": { "@ref": "databases/personnel" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "personnel"
},
{
"ref": { "@ref": "databases/bulletin-board" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "bulletin-board"
}
]
[
{
ref: ref(id = "personnel", class = ref(id = "databases")),
ts: 1520225711114944,
name: "personnel"
},
{
ref: ref(id = "bulletin-board", class = ref(id = "databases")),
ts: 1520225711114944,
name: "bulletin-board"
}
]
[
{
"ref": { "@ref": "databases/personnel" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "personnel"
},
{
"ref": { "@ref": "databases/bulletin-board" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "bulletin-board"
}
]
[
{
"ref": { "@ref": "databases/personnel" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "personnel"
},
{
"ref": { "@ref": "databases/bulletin-board" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "bulletin-board"
}
]
[
{
"ref": { "@ref": "databases/personnel" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "personnel"
},
{
"ref": { "@ref": "databases/bulletin-board" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "bulletin-board"
}
]
[
{
"ref": { "@ref": "databases/personnel" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "personnel"
},
{
"ref": { "@ref": "databases/bulletin-board" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "bulletin-board"
}
]
[
{
"ref": { "@ref": "databases/personnel" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "personnel"
},
{
"ref": { "@ref": "databases/bulletin-board" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "bulletin-board"
}
]
[
{
"ref": { "@ref": "databases/personnel" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "personnel"
},
{
"ref": { "@ref": "databases/bulletin-board" },
"class": { "@ref": "databases" },
"ts": 1520225711114944,
"name": "bulletin-board"
}
]
Finally, we create a server key for each new internal database. These keys will be used within the app fronting the database.
curl https://db.fauna.com/ \
-u fnACrVR4cUAGAMbQBucJV2d-yiDy2mDDlOBWUd6A: \
-d '{
"map": {
"lambda": "db",
"expr": {
"create_key": {
"object": { "role": "server", "database": { "var": "db" } }
}
}
},
"collection": [
{ "database": "personnel" },
{ "database": "bulletin-board" }
]
}'
client.Query(
Map(
Arr(Database("personnel"), Database("bulletin-board")),
db => CreateKey(Obj("role", "server", "database", db))));
client.query(
Map(
Arr(
Database(Value("personnel")),
Database(Value("bulletin-board"))
),
Lambda(
Value("db"),
CreateKey(
Obj("role", Value("server"), "database", Var("db"))))));
client.Query(
f.Map(
f.Arr{f.Database("personnel"), f.Database("bulletin-board")},
f.Lambda(
"db",
f.CreateKey(
f.Obj{"role": "server", "database": f.Var("db")},
),
),
),
)
client.query(
Map(
Arr(Database("personnel"), Database("bulletin-board")),
Lambda { db =>
CreateKey(Obj("role" -> "server", "database" -> db))
}))
client.query(
q.map_expr(
lambda db: q.create_key({"role": "server", "database": db}),
[q.database("personnel"), q.database("bulletin-board")]
))
$client.query do
map [database('personnel'), database('bulletin-board')] do |db|
create_key(role: 'server', database: db)
end
end
client.query(
Map(
collection: Arr(Database("personnel"), Database("bulletin-board")),
to: { db in
CreateKey(
Obj("role" => "server", "database" => db)
)
}
)
)
client.query(
q.Map(
[q.Database("personnel"), q.Database("bulletin-board")],
function(db) {
return q.CreateKey({ role: "server", database: db });
}));
HTTP/1.1 200 OK
{
"resource": [
{
"ref": { "@ref": "keys/192903235415048704" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/personnel" },
"secret": "fnACrVR4dvACAE_6j47h083I_y0JwDduoIc0mxU_",
"hashed_secret": "$2a$05$L3MV3akG.sTzRARbjbZ3xO5d96Xj8EGkJbkYRO1igIWo1kbQh0N2C"
},
{
"ref": { "@ref": "keys/192903235415049728" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/bulletin-board" },
"secret": "fnACrVR4dvAGABy_lWsYaoWFk8VEh9204DjFeQS8",
"hashed_secret": "$2a$05$mBsAZ9X0PUf3g0naTM7m.eeeb6eS7aO2aNiDgY7R7yG8Hg0kL/tjW"
}
]
}
[
{
"ref": { "@ref": "keys/192903235415048704" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/personnel" },
"secret": "fnACrVR4dvACAE_6j47h083I_y0JwDduoIc0mxU_",
"hashed_secret": "$2a$05$L3MV3akG.sTzRARbjbZ3xO5d96Xj8EGkJbkYRO1igIWo1kbQh0N2C"
},
{
"ref": { "@ref": "keys/192903235415049728" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/bulletin-board" },
"secret": "fnACrVR4dvAGABy_lWsYaoWFk8VEh9204DjFeQS8",
"hashed_secret": "$2a$05$mBsAZ9X0PUf3g0naTM7m.eeeb6eS7aO2aNiDgY7R7yG8Hg0kL/tjW"
}
]
[
{
ref: ref(id = "192903235415048704", class = ref(id = "keys")),
ts: 1520225711155247,
role: "server",
database: ref(id = "personnel", class = ref(id = "databases")),
secret: "fnAC6mqlqqACAJJjiGTlhHDrz5qyvhSKLAoTbIho",
hashed_secret: "$2a$05$qoSM2o7Rb.p9Sds5RJyx8uPmLoP/CRPjbni3/hCTlJ/rJmeWnnoIS"
},
{
ref: ref(id = "192903235415049728", class = ref(id = "keys")),
ts: 1520225711155247,
role: "server",
database: ref(id = "bulletin-board", class = ref(id = "databases")),
secret: "fnAC6mqlrDACAFXcquZ1ZsP_OLeN-YVS5ACBoeXR",
hashed_secret: "$2a$05$Uf1Tl0XE9RlKpucKjFPWIuSlsRv/aOPtbvHDP08jJs2HHjxZ/0ERG"
}
]
[
{
"ref": { "@ref": "keys/192903235415048704" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/personnel" },
"secret": "fnACrVR4dvACAE_6j47h083I_y0JwDduoIc0mxU_",
"hashed_secret": "$2a$05$L3MV3akG.sTzRARbjbZ3xO5d96Xj8EGkJbkYRO1igIWo1kbQh0N2C"
},
{
"ref": { "@ref": "keys/192903235415049728" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/bulletin-board" },
"secret": "fnACrVR4dvAGABy_lWsYaoWFk8VEh9204DjFeQS8",
"hashed_secret": "$2a$05$mBsAZ9X0PUf3g0naTM7m.eeeb6eS7aO2aNiDgY7R7yG8Hg0kL/tjW"
}
]
[
{
"ref": { "@ref": "keys/192903235415048704" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/personnel" },
"secret": "fnACrVR4dvACAE_6j47h083I_y0JwDduoIc0mxU_",
"hashed_secret": "$2a$05$L3MV3akG.sTzRARbjbZ3xO5d96Xj8EGkJbkYRO1igIWo1kbQh0N2C"
},
{
"ref": { "@ref": "keys/192903235415049728" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/bulletin-board" },
"secret": "fnACrVR4dvAGABy_lWsYaoWFk8VEh9204DjFeQS8",
"hashed_secret": "$2a$05$mBsAZ9X0PUf3g0naTM7m.eeeb6eS7aO2aNiDgY7R7yG8Hg0kL/tjW"
}
]
[
{
"ref": { "@ref": "keys/192903235415048704" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/personnel" },
"secret": "fnACrVR4dvACAE_6j47h083I_y0JwDduoIc0mxU_",
"hashed_secret": "$2a$05$L3MV3akG.sTzRARbjbZ3xO5d96Xj8EGkJbkYRO1igIWo1kbQh0N2C"
},
{
"ref": { "@ref": "keys/192903235415049728" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/bulletin-board" },
"secret": "fnACrVR4dvAGABy_lWsYaoWFk8VEh9204DjFeQS8",
"hashed_secret": "$2a$05$mBsAZ9X0PUf3g0naTM7m.eeeb6eS7aO2aNiDgY7R7yG8Hg0kL/tjW"
}
]
[
{
"ref": { "@ref": "keys/192903235415048704" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/personnel" },
"secret": "fnACrVR4dvACAE_6j47h083I_y0JwDduoIc0mxU_",
"hashed_secret": "$2a$05$L3MV3akG.sTzRARbjbZ3xO5d96Xj8EGkJbkYRO1igIWo1kbQh0N2C"
},
{
"ref": { "@ref": "keys/192903235415049728" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/bulletin-board" },
"secret": "fnACrVR4dvAGABy_lWsYaoWFk8VEh9204DjFeQS8",
"hashed_secret": "$2a$05$mBsAZ9X0PUf3g0naTM7m.eeeb6eS7aO2aNiDgY7R7yG8Hg0kL/tjW"
}
]
[
{
"ref": { "@ref": "keys/192903235415048704" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/personnel" },
"secret": "fnACrVR4dvACAE_6j47h083I_y0JwDduoIc0mxU_",
"hashed_secret": "$2a$05$L3MV3akG.sTzRARbjbZ3xO5d96Xj8EGkJbkYRO1igIWo1kbQh0N2C"
},
{
"ref": { "@ref": "keys/192903235415049728" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/bulletin-board" },
"secret": "fnACrVR4dvAGABy_lWsYaoWFk8VEh9204DjFeQS8",
"hashed_secret": "$2a$05$mBsAZ9X0PUf3g0naTM7m.eeeb6eS7aO2aNiDgY7R7yG8Hg0kL/tjW"
}
]
[
{
"ref": { "@ref": "keys/192903235415048704" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/personnel" },
"secret": "fnACrVR4dvACAE_6j47h083I_y0JwDduoIc0mxU_",
"hashed_secret": "$2a$05$L3MV3akG.sTzRARbjbZ3xO5d96Xj8EGkJbkYRO1igIWo1kbQh0N2C"
},
{
"ref": { "@ref": "keys/192903235415049728" },
"class": { "@ref": "keys" },
"ts": 1520225711155247,
"role": "server",
"database": { "@ref": "databases/bulletin-board" },
"secret": "fnACrVR4dvAGABy_lWsYaoWFk8VEh9204DjFeQS8",
"hashed_secret": "$2a$05$mBsAZ9X0PUf3g0naTM7m.eeeb6eS7aO2aNiDgY7R7yG8Hg0kL/tjW"
}
]
Conclusion
In this page we walked through setting up a hierarchy of databases starting with two top-level, broadly scoped databases and continuing down to individual databases for internal products. Keys for the individual app databases are unable to access anything outside of their associated database.
FaunaDB Cloud works identically. An organization can build their database hierarchy according to their structure without the overhead of operating their own FaunaDB cluster.
Was this article helpful?
We're sorry to hear that.
Tell us how we can improve!
documentation@fauna.com
Thank you for your feedback!