SlideShare a Scribd company logo
Content Delivery
At Aviary
MongoDb User Group 11/19/13
Aviary
Photo-Editing
SDK & Apps
Fully-Baked UI
Configurable, High-Quality Tools
Over 5,000 Partners
Over 50 Million Monthly Users
Over 4 Billion Photos Edited
iOS, Android, Web, Windows, Server
J
Who Are We?
Nir

Jack

Lead Serverside

Director of

Engineer

Engineering

Likes:
●
●
●

Automated deployment
Big-O notation
Brainteasers

Hates:
●

Cilantro

Likes:
●
●
●

Parallelizing processes
DRY code
Seltzer

Hates:
●

Food after the sell-by date
Content
Effects

Frames

Stickers

Messages

J
The “Fat Tiny” Situation
We want to dynamically deliver the Fat Tiny
stickers to our users

How can we do that?
J
The CDS
Aviary’s Content Delivery System
Version 1
● Static files on S3
● Excess data sent
● Data stored in MySQL
● New features meant new code

N
The “Fat Tiny” Situation
We want to display the Fat Tiny sticker pack only
to Picstitch users in Japan who use iOS 7

How can we do that?
N
CDS V2
Version 2 Overview
Stack
Global
Users

Akamai

AWS Cloud Formation
AWS Elastic LoadBalancer (ELB)
Node.js
AWS Elastic Cloud Computing (EC2)
Ubuntu
Bash
MongoDb
JSON
JSON Schema

Content
Delivery
Network

Load Balancer

API
Servers
Database
Cluster
Management
System

N
Why MongoDB?
● Great with Node (JSON-based)
● Schema-less is easy to change/query
● Read-heavy
● Relatively small data set

N
How It Works
A Behind-the-Scenes Look
Delivered Types
● Manifest JSON
○ Content Set
○ Content Versions

● Content JSON
○ Content Metadata
○ All Assets

N
The “Fat Tiny” Situation
We want to manage the Fat Tiny sticker pack
as a single entity, but we want to deliver it to
each device in its own
optimal format.
How can we do that?
N
Response Formatting Model
Content Entry

Response Formats

Responses

JSON document describing
content item

JSON documents defining mappings
from entry to responses

Actual JSON responses
delivered to devices

J
Content Formats
● JSON schema

{
"type":"object",
"properties":{
"metadata": {

● Added properties

"type": "object",
"properties":{
"displayName": {
"type": "string",

● Custom types

}
}
},

● Validates entries

"icon": {
"type": "object",
"customType": "image"
"properties":{
"path": {
"type": "string",
"required": true,

J
Response Formats
● JSON schema

{
"type":"object",
"properties":{
"identifier": {

● dataKey property

"type": "string",
"dataKey": "identifier"
},

● Defines response

"name": {
"type": "string",
"dataKey": "metadata.displayName"
},

structure

"iconImagePath": {
"type": "string",
"dataKey": "icon.path-100"

● Maps content

},
"items": {
"type": "array",
"dataKey": "items"

J
Content Deployment
1. Insert/Update CMS Entry
"identifier": "com.aviary.stickers.234fe"

2. Find Response Formats
"type":"object",

"id": "com.aviary.stickers.234fe",

"properties":{

"metadata": {
"displayName": "Hats"

"name": "Hats",

"id": {
"type": "string",

},

"dataKey": "identifier"

"icon": {
"path": "cds/hats/icon.png"

"iconImagePath": "cds/hats/icon100.png"
"stickers": [
{

},

"identifier": "1"

"name": {

"path-100": "cds/hats/icon100.png"

"type": "string",

},

"imageUrl": "cds/hats/1.png"

"dataKey": "metadata.displayName"

"items": [

},

{

"type": "string",

"imageUrl": "cds/hats/1.png"
}

}
],

"iconImagePath": {

"identifier": "1"

]

3. Generate+Insert Responses

"versionKey": "e4532fd342"

"dataKey": "icon.path-100"
},
"stickers": {
"type": "array",
"dataKey": "items"

J
Manifests
"stickers": [
{
"id": "com.aviary.stickers.234fe",
"versionKey": "e4532fd342"
},
{
"id": "com.aviary.stickers.fed34",
"versionKey": "c54532343d"
}
],
"frames": [
{
"id": "com.aviary.frames.25435",
"versionKey": "fd4324323"
}
]

J
Manifest Deployment
Using Aggregate to Find the Newest Versions

Manifest with Correct Version Keys

{
$match:{

"stickers": [
{

formatId:{$in:formatIds},

"id": "com.aviary.stickers.234fe",

identifier:{$in:identifiers}

"versionKey": "e4532fd342"

}
}

},
],

{
$sort: { _id: -1 }

"effects": [
{

},

"id": "com.aviary.effects.25435",

{

"versionKey": "fd4324323"

$group: {
}

_id: "$identifier",
versionKey:{$first:"$versionKey"}

]

}
}

J
Scopes and Targeting
Deployed Manifests Have Scopes

End Users Have Scope Parameters

Manifest 1
"targetingScope": {
"apiKey": "abc",
"country": ["JP"]
},

/manifest?

"formattingScope": {
"platform": "ios",
"minOsVersion": "7.0.0"
}

apiKey=abc&
country=JP&
language=ja&
platform=ios&

Manifest 2

osVersion=7.2.0

"targetingScope": {
"apiKey": "def",
},
"formattingScope": {
"platform": "android",
"minOsVersion": "6.0.0"
}

N
API Servers
Scope parameters are converted into queries
Manifest 1
"targetingScope": {
db.manifest.find({

"apiKey": "abc",

"apiKey": {$in: ["abc", null]},
/manifest?

country=JP&

"formattingScope": {

"platform": {$in: ["ios", null]},
7002000

"platform": "ios",

"minOsVersion": {$lte: 7002000}

language=ja&

osVersion=7.2.0

},

"language": {$in: ["ja", null]},

apiKey=abc&

platform=ios&

"country": ["JP"]

"country": {$in: ["JP", null]},

"minOsVersion": "7.0.0"

}).sort({

}

"apiKey": -1,

Manifest 2

"language": -1,

"targetingScope": {

"country": -1,

"apiKey": "abc",

"minOsVersion": -1,

},

"platform": -1,

"formattingScope": {

"_id": -1

"platform": "ios",

}).limit(1)

"minOsVersion": "6.0.0"
}

N
Versioned Content
Received Manifests Contain VersionKeys
"stickers": [
{
"id": "com.aviary.stickers.234fe",
"versionKey": "e4532fd342"
},
{
"id": "com.aviary.stickers.fed34",
"versionKey": "c54532343d"

db.content.findOne({
/content?
versionKey=e4532fd342

}

"versionKey": “e4532fd342”
});

],
"frames": [
{
"id": "com.aviary.frames.25435",
"versionKey": "fd4324323"
}
]

N
Response Caching
db.manifests.find({

/manifest?

"apiKey": {$in: ["abc", null]},

apiKey=abc&

"country": {$in: ["JP", null]},

country=JP&

"language": {$in: ["ja", null]},

language=ja&

"platform": {$in: ["ios", null]},

platform=ios&

"minOsVersion": {$gte: 7002000}

osVersion=7.2.0

}).sort({
…,
"_id": -1
}).limit(1)

db.cachedManifests.findOne({
"url": "/manifest?apiKey=abc&country=JP&language=ja&osVersion=7.2.0&platform=ios"
})

N
PAULA
The CDS Management Console
Auto-generated UI

J
Other Mongo Usage
● PAULA permissions in user objects
users collection
{
"name": "nir",
"email": "nir@aviary.com",
"permissions": [
"content",
"dev",
"admin",
"partying"
]
}

● Integration tests interact with schemaless db willy nilly
N
Conclusion
The Takeaway
The Facts
● Built and deployed in 3 months
● Very few struggles with MongoDB
● Seamless management
● Graceful scaling from 0 to over 20M MAUs
● Happy serverside engineers
J
The Future
● Targeted Translations
● Granular User Targeting
● PAULA for the masses

N
Questions?
Comments also welcome
nir@aviary.com

jack@aviary.com

…and by the way, WE’RE HIRING!

More Related Content

PDF
google drive and the google drive sdk
PDF
jQuery State of the Union - Yehuda Katz
PPSX
JQuery Comprehensive Overview
PPTX
Google Drive & Google Drive SDK
PPTX
Data Science using Google Cloud BigQuery, Python and Power BI
KEY
Building HTTP API's with NodeJS and MongoDB
PDF
Node in Production at Aviary
PDF
Frontend APIs powering fast paced product iterations
google drive and the google drive sdk
jQuery State of the Union - Yehuda Katz
JQuery Comprehensive Overview
Google Drive & Google Drive SDK
Data Science using Google Cloud BigQuery, Python and Power BI
Building HTTP API's with NodeJS and MongoDB
Node in Production at Aviary
Frontend APIs powering fast paced product iterations

Similar to MongoDB and Content Delivery at Aviary by Nir Zicherman and Jack Sisson (20)

PDF
RICOH THETA x IoT Developers Contest : Cloud API Seminar (2nd installation)
PDF
Engineering the New LinkedIn Profile
PDF
Exploring Google (Cloud) APIs with Python & JavaScript
PPTX
Build 2017 - B8002 - Introducing Adaptive Cards
PPTX
Getting started with titanium
PDF
Using Google (Cloud) APIs
PDF
The Rise of NoSQL
PDF
Architecting for change: LinkedIn's new data ecosystem
PDF
Strata 2016 - Architecting for Change: LinkedIn's new data ecosystem
PPTX
Windows 8 Pure Imagination - 2012-11-24 - Getting your HTML5 game Windows 8 r...
PPTX
Getting started with Appcelerator Titanium
PPTX
Microsoft Graph: Connect to essential data every app needs
PPTX
Microsoft Graph: Connect to essential data every app needs
PPTX
Building Your First App with MongoDB Stitch
KEY
Appcelerator iPhone/iPad Dev Con 2010 San Diego, CA
ZIP
iPhone/iPad Development with Titanium
PDF
Power your apps with Gmail, Google Drive, Calendar, Sheets, Slides & more
PDF
Fixing Gaps. Strengthening the Chromium platform for content blocking
PDF
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
PDF
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
RICOH THETA x IoT Developers Contest : Cloud API Seminar (2nd installation)
Engineering the New LinkedIn Profile
Exploring Google (Cloud) APIs with Python & JavaScript
Build 2017 - B8002 - Introducing Adaptive Cards
Getting started with titanium
Using Google (Cloud) APIs
The Rise of NoSQL
Architecting for change: LinkedIn's new data ecosystem
Strata 2016 - Architecting for Change: LinkedIn's new data ecosystem
Windows 8 Pure Imagination - 2012-11-24 - Getting your HTML5 game Windows 8 r...
Getting started with Appcelerator Titanium
Microsoft Graph: Connect to essential data every app needs
Microsoft Graph: Connect to essential data every app needs
Building Your First App with MongoDB Stitch
Appcelerator iPhone/iPad Dev Con 2010 San Diego, CA
iPhone/iPad Development with Titanium
Power your apps with Gmail, Google Drive, Calendar, Sheets, Slides & more
Fixing Gaps. Strengthening the Chromium platform for content blocking
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Ad

More from Hakka Labs (20)

PDF
Always Valid Inference (Ramesh Johari, Stanford)
PPTX
DataEngConf SF16 - High cardinality time series search
PDF
DataEngConf SF16 - Data Asserts: Defensive Data Science
PDF
DatEngConf SF16 - Apache Kudu: Fast Analytics on Fast Data
PDF
DataEngConf SF16 - Recommendations at Instacart
PDF
DataEngConf SF16 - Running simulations at scale
PDF
DataEngConf SF16 - Deriving Meaning from Wearable Sensor Data
PDF
DataEngConf SF16 - Collecting and Moving Data at Scale
PDF
DataEngConf SF16 - BYOMQ: Why We [re]Built IronMQ
PDF
DataEngConf SF16 - Unifying Real Time and Historical Analytics with the Lambd...
PDF
DataEngConf SF16 - Three lessons learned from building a production machine l...
PDF
DataEngConf SF16 - Scalable and Reliable Logging at Pinterest
PDF
DataEngConf SF16 - Bridging the gap between data science and data engineering
PDF
DataEngConf SF16 - Multi-temporal Data Structures
PDF
DataEngConf SF16 - Entity Resolution in Data Pipelines Using Spark
PDF
DataEngConf SF16 - Beginning with Ourselves
PDF
DataEngConf SF16 - Routing Billions of Analytics Events with High Deliverability
PDF
DataEngConf SF16 - Tales from the other side - What a hiring manager wish you...
PDF
DataEngConf SF16 - Methods for Content Relevance at LinkedIn
PDF
DataEngConf SF16 - Spark SQL Workshop
Always Valid Inference (Ramesh Johari, Stanford)
DataEngConf SF16 - High cardinality time series search
DataEngConf SF16 - Data Asserts: Defensive Data Science
DatEngConf SF16 - Apache Kudu: Fast Analytics on Fast Data
DataEngConf SF16 - Recommendations at Instacart
DataEngConf SF16 - Running simulations at scale
DataEngConf SF16 - Deriving Meaning from Wearable Sensor Data
DataEngConf SF16 - Collecting and Moving Data at Scale
DataEngConf SF16 - BYOMQ: Why We [re]Built IronMQ
DataEngConf SF16 - Unifying Real Time and Historical Analytics with the Lambd...
DataEngConf SF16 - Three lessons learned from building a production machine l...
DataEngConf SF16 - Scalable and Reliable Logging at Pinterest
DataEngConf SF16 - Bridging the gap between data science and data engineering
DataEngConf SF16 - Multi-temporal Data Structures
DataEngConf SF16 - Entity Resolution in Data Pipelines Using Spark
DataEngConf SF16 - Beginning with Ourselves
DataEngConf SF16 - Routing Billions of Analytics Events with High Deliverability
DataEngConf SF16 - Tales from the other side - What a hiring manager wish you...
DataEngConf SF16 - Methods for Content Relevance at LinkedIn
DataEngConf SF16 - Spark SQL Workshop
Ad

Recently uploaded (20)

PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Review of recent advances in non-invasive hemoglobin estimation
PPTX
MYSQL Presentation for SQL database connectivity
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
cuic standard and advanced reporting.pdf
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PPTX
Cloud computing and distributed systems.
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
Big Data Technologies - Introduction.pptx
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
The Rise and Fall of 3GPP – Time for a Sabbatical?
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Dropbox Q2 2025 Financial Results & Investor Presentation
20250228 LYD VKU AI Blended-Learning.pptx
Review of recent advances in non-invasive hemoglobin estimation
MYSQL Presentation for SQL database connectivity
The AUB Centre for AI in Media Proposal.docx
Reach Out and Touch Someone: Haptics and Empathic Computing
cuic standard and advanced reporting.pdf
“AI and Expert System Decision Support & Business Intelligence Systems”
Cloud computing and distributed systems.
NewMind AI Weekly Chronicles - August'25 Week I
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Chapter 3 Spatial Domain Image Processing.pdf
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Big Data Technologies - Introduction.pptx
Mobile App Security Testing_ A Comprehensive Guide.pdf

MongoDB and Content Delivery at Aviary by Nir Zicherman and Jack Sisson

  • 2. Aviary Photo-Editing SDK & Apps Fully-Baked UI Configurable, High-Quality Tools Over 5,000 Partners Over 50 Million Monthly Users Over 4 Billion Photos Edited iOS, Android, Web, Windows, Server J
  • 3. Who Are We? Nir Jack Lead Serverside Director of Engineer Engineering Likes: ● ● ● Automated deployment Big-O notation Brainteasers Hates: ● Cilantro Likes: ● ● ● Parallelizing processes DRY code Seltzer Hates: ● Food after the sell-by date
  • 5. The “Fat Tiny” Situation We want to dynamically deliver the Fat Tiny stickers to our users How can we do that? J
  • 6. The CDS Aviary’s Content Delivery System
  • 7. Version 1 ● Static files on S3 ● Excess data sent ● Data stored in MySQL ● New features meant new code N
  • 8. The “Fat Tiny” Situation We want to display the Fat Tiny sticker pack only to Picstitch users in Japan who use iOS 7 How can we do that? N
  • 9. CDS V2 Version 2 Overview
  • 10. Stack Global Users Akamai AWS Cloud Formation AWS Elastic LoadBalancer (ELB) Node.js AWS Elastic Cloud Computing (EC2) Ubuntu Bash MongoDb JSON JSON Schema Content Delivery Network Load Balancer API Servers Database Cluster Management System N
  • 11. Why MongoDB? ● Great with Node (JSON-based) ● Schema-less is easy to change/query ● Read-heavy ● Relatively small data set N
  • 12. How It Works A Behind-the-Scenes Look
  • 13. Delivered Types ● Manifest JSON ○ Content Set ○ Content Versions ● Content JSON ○ Content Metadata ○ All Assets N
  • 14. The “Fat Tiny” Situation We want to manage the Fat Tiny sticker pack as a single entity, but we want to deliver it to each device in its own optimal format. How can we do that? N
  • 15. Response Formatting Model Content Entry Response Formats Responses JSON document describing content item JSON documents defining mappings from entry to responses Actual JSON responses delivered to devices J
  • 16. Content Formats ● JSON schema { "type":"object", "properties":{ "metadata": { ● Added properties "type": "object", "properties":{ "displayName": { "type": "string", ● Custom types } } }, ● Validates entries "icon": { "type": "object", "customType": "image" "properties":{ "path": { "type": "string", "required": true, J
  • 17. Response Formats ● JSON schema { "type":"object", "properties":{ "identifier": { ● dataKey property "type": "string", "dataKey": "identifier" }, ● Defines response "name": { "type": "string", "dataKey": "metadata.displayName" }, structure "iconImagePath": { "type": "string", "dataKey": "icon.path-100" ● Maps content }, "items": { "type": "array", "dataKey": "items" J
  • 18. Content Deployment 1. Insert/Update CMS Entry "identifier": "com.aviary.stickers.234fe" 2. Find Response Formats "type":"object", "id": "com.aviary.stickers.234fe", "properties":{ "metadata": { "displayName": "Hats" "name": "Hats", "id": { "type": "string", }, "dataKey": "identifier" "icon": { "path": "cds/hats/icon.png" "iconImagePath": "cds/hats/icon100.png" "stickers": [ { }, "identifier": "1" "name": { "path-100": "cds/hats/icon100.png" "type": "string", }, "imageUrl": "cds/hats/1.png" "dataKey": "metadata.displayName" "items": [ }, { "type": "string", "imageUrl": "cds/hats/1.png" } } ], "iconImagePath": { "identifier": "1" ] 3. Generate+Insert Responses "versionKey": "e4532fd342" "dataKey": "icon.path-100" }, "stickers": { "type": "array", "dataKey": "items" J
  • 19. Manifests "stickers": [ { "id": "com.aviary.stickers.234fe", "versionKey": "e4532fd342" }, { "id": "com.aviary.stickers.fed34", "versionKey": "c54532343d" } ], "frames": [ { "id": "com.aviary.frames.25435", "versionKey": "fd4324323" } ] J
  • 20. Manifest Deployment Using Aggregate to Find the Newest Versions Manifest with Correct Version Keys { $match:{ "stickers": [ { formatId:{$in:formatIds}, "id": "com.aviary.stickers.234fe", identifier:{$in:identifiers} "versionKey": "e4532fd342" } } }, ], { $sort: { _id: -1 } "effects": [ { }, "id": "com.aviary.effects.25435", { "versionKey": "fd4324323" $group: { } _id: "$identifier", versionKey:{$first:"$versionKey"} ] } } J
  • 21. Scopes and Targeting Deployed Manifests Have Scopes End Users Have Scope Parameters Manifest 1 "targetingScope": { "apiKey": "abc", "country": ["JP"] }, /manifest? "formattingScope": { "platform": "ios", "minOsVersion": "7.0.0" } apiKey=abc& country=JP& language=ja& platform=ios& Manifest 2 osVersion=7.2.0 "targetingScope": { "apiKey": "def", }, "formattingScope": { "platform": "android", "minOsVersion": "6.0.0" } N
  • 22. API Servers Scope parameters are converted into queries Manifest 1 "targetingScope": { db.manifest.find({ "apiKey": "abc", "apiKey": {$in: ["abc", null]}, /manifest? country=JP& "formattingScope": { "platform": {$in: ["ios", null]}, 7002000 "platform": "ios", "minOsVersion": {$lte: 7002000} language=ja& osVersion=7.2.0 }, "language": {$in: ["ja", null]}, apiKey=abc& platform=ios& "country": ["JP"] "country": {$in: ["JP", null]}, "minOsVersion": "7.0.0" }).sort({ } "apiKey": -1, Manifest 2 "language": -1, "targetingScope": { "country": -1, "apiKey": "abc", "minOsVersion": -1, }, "platform": -1, "formattingScope": { "_id": -1 "platform": "ios", }).limit(1) "minOsVersion": "6.0.0" } N
  • 23. Versioned Content Received Manifests Contain VersionKeys "stickers": [ { "id": "com.aviary.stickers.234fe", "versionKey": "e4532fd342" }, { "id": "com.aviary.stickers.fed34", "versionKey": "c54532343d" db.content.findOne({ /content? versionKey=e4532fd342 } "versionKey": “e4532fd342” }); ], "frames": [ { "id": "com.aviary.frames.25435", "versionKey": "fd4324323" } ] N
  • 24. Response Caching db.manifests.find({ /manifest? "apiKey": {$in: ["abc", null]}, apiKey=abc& "country": {$in: ["JP", null]}, country=JP& "language": {$in: ["ja", null]}, language=ja& "platform": {$in: ["ios", null]}, platform=ios& "minOsVersion": {$gte: 7002000} osVersion=7.2.0 }).sort({ …, "_id": -1 }).limit(1) db.cachedManifests.findOne({ "url": "/manifest?apiKey=abc&country=JP&language=ja&osVersion=7.2.0&platform=ios" }) N
  • 27. Other Mongo Usage ● PAULA permissions in user objects users collection { "name": "nir", "email": "nir@aviary.com", "permissions": [ "content", "dev", "admin", "partying" ] } ● Integration tests interact with schemaless db willy nilly N
  • 29. The Facts ● Built and deployed in 3 months ● Very few struggles with MongoDB ● Seamless management ● Graceful scaling from 0 to over 20M MAUs ● Happy serverside engineers J
  • 30. The Future ● Targeted Translations ● Granular User Targeting ● PAULA for the masses N