MongoDB Atlas App Services
Build serverless applications with MongoDB
🚀 What is Atlas App Services?
Atlas App Services is a serverless platform for building modern applications. It provides authentication, data access rules, serverless functions, and triggers, eliminating the need for backend infrastructure management.
// Simple App Services Function
exports = async function() {
const mongodb = context.services.get("mongodb-atlas");
const users = mongodb.db("myapp").collection("users");
return await users.find().toArray();
};
Output:
[{ name: "Alice" }, { name: "Bob" }]
Key Features
Authentication
Built-in user authentication and management
// Email/Password login
const user = await app.logIn(
Realm.Credentials.emailPassword(
"[email protected]",
"password123"
)
);
Data Access Rules
Control who can read and write data
{
"roles": [{
"name": "owner",
"apply_when": {
"userId": "%%user.id"
},
"read": true,
"write": true
}]
}
Functions
Serverless JavaScript functions
// Custom function
exports = function(name) {
return `Hello, ${name}!`;
};
GraphQL API
Auto-generated GraphQL endpoints
query {
users {
name
email
}
}
🔹 Setting Up Authentication
App Services provides multiple authentication methods including email/password, API keys, Google, Facebook, and custom JWT. Authentication is configured through the Atlas UI and requires minimal code implementation.
// Initialize App Services
import Realm from "realm-web";
const app = new Realm.App({ id: "myapp-abcde" });
// Email/Password Authentication
async function loginUser(email, password) {
try {
const credentials = Realm.Credentials.emailPassword(email, password);
const user = await app.logIn(credentials);
console.log("Logged in as:", user.id);
return user;
} catch (error) {
console.error("Login failed:", error);
}
}
// Anonymous Authentication
async function loginAnonymous() {
const credentials = Realm.Credentials.anonymous();
const user = await app.logIn(credentials);
console.log("Anonymous user:", user.id);
return user;
}
// API Key Authentication
async function loginWithApiKey(apiKey) {
const credentials = Realm.Credentials.apiKey(apiKey);
const user = await app.logIn(credentials);
return user;
}
Output:
Logged in as: 507f1f77bcf86cd799439011
🔹 Creating Serverless Functions
Functions run server-side JavaScript code without managing servers. They can access MongoDB, call external APIs, and execute business logic. Functions are perfect for data validation, processing, and integration tasks.
// Function: createUser
exports = async function(userData) {
const mongodb = context.services.get("mongodb-atlas");
const users = mongodb.db("myapp").collection("users");
// Validate input
if (!userData.email || !userData.name) {
throw new Error("Email and name are required");
}
// Check if user exists
const existing = await users.findOne({ email: userData.email });
if (existing) {
throw new Error("User already exists");
}
// Create user
const result = await users.insertOne({
...userData,
createdAt: new Date(),
userId: context.user.id
});
return {
success: true,
userId: result.insertedId
};
};
// Call function from client
const result = await user.functions.createUser({
name: "Alice",
email: "[email protected]"
});
Output:
{ success: true, userId: "507f191e810c19729de860ea" }
🔹 Data Access Rules
Rules control database access at the document level. Define who can read, write, or delete data based on user identity, document fields, or custom logic for secure data access.
// Collection Rules Configuration
{
"database": "myapp",
"collection": "posts",
"roles": [
{
"name": "owner",
"apply_when": {
"userId": "%%user.id"
},
"fields": {
"title": { "read": true, "write": true },
"content": { "read": true, "write": true },
"userId": { "read": true, "write": false }
},
"read": true,
"write": true,
"insert": true,
"delete": true
},
{
"name": "public",
"apply_when": {},
"fields": {
"title": { "read": true },
"content": { "read": true }
},
"read": true,
"write": false
}
]
}
Rule Explanation:
- owner role: Users can read/write their own posts
- public role: Everyone can read all posts
- Field-level security: Control access to specific fields
🔹 Using GraphQL API
App Services automatically generates GraphQL APIs from your MongoDB collections. Query and mutate data using GraphQL syntax without writing resolver functions, perfect for modern frontend frameworks.
// GraphQL Query
const query = `
query GetUsers {
users {
_id
name
email
}
}
`;
// Execute query
const response = await user.functions.graphql(query);
console.log(response.users);
// GraphQL Mutation
const mutation = `
mutation CreatePost($data: PostInsertInput!) {
insertOnePost(data: $data) {
_id
title
}
}
`;
const variables = {
data: {
title: "My First Post",
content: "Hello World!",
userId: user.id
}
};
const result = await user.functions.graphql(mutation, variables);
Output:
{ _id: "507f1f77bcf86cd799439011", title: "My First Post" }
🔹 Calling External APIs
Functions can make HTTP requests to external services:
// Function: getWeather
exports = async function(city) {
const response = await context.http.get({
url: `https://api.weather.com/v1/current?city=${city}`,
headers: { "API-Key": ["myapikey"] }
});
const weather = JSON.parse(response.body.text());
return {
city: city,
temperature: weather.temp,
condition: weather.condition
};
};
🔹 Best Practices
Follow these guidelines for App Services:
- Use rules: Always define data access rules for security
- Validate input: Check function parameters before processing
- Handle errors: Use try-catch blocks in functions
- Optimize queries: Use indexes and limit results
- Monitor usage: Check logs and metrics regularly