Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MongoDB and REST APIs A Match Made in Heaven

MongoDB and REST APIs A Match Made in Heaven

Exposing MongoDB over the internet through a RESTful API is becoming a common pattern, and for very good reasons. Your REST API provides a nice layer of abstraction, isolation and validation above the actual datastore while providing access to all kind of clients. At the same time MongoDB, with its BSON store, is ideal for serving data over the Internet. But designing first, and then building a robust and scalable REST API is not an easy task.

EVE is an open source framework allowing anyone to effortlessly expose MongoDB data sources over highly customizable, fully featured RESTful Web Services. Initially developed to solve our own internal use case, EVE has been getting a lot of traction since its open source release in 2012.

In this talk I will go through the reasons that make MongoDB a good match for most RESTful APIs. I will then show some prominent EVE features and illustrate how one can quickly and easily go online with a RESTful MongoDB front-end. I also plan to illustrate some common pitfalls on MongoDB+EVE/REST deployments.

Nicola Iarocci

October 16, 2015
Tweet

More Decks by Nicola Iarocci

Other Decks in Technology

Transcript

  1. Good Morning
    Percona Live Amsterdam 2015

    View full-size slide

  2. Who Am I
    fighting back against impostor syndrome

    View full-size slide

  3. Nicola Iarocci
    Co-founder and CTO at CIR 2000

    View full-size slide

  4. Nicola Iarocci
    MongoDB Master

    View full-size slide

  5. Nicola Iarocci
    Open Source junkie
    Eve •
    Cerberus •
    Events •
    Flask-Sentinel •
    Eve.NET •
    Etc.

    View full-size slide

  6. Nicola Iarocci
    Consultant
    Mongo • RESTful Services • Python • My Open Source Projects

    View full-size slide

  7. Nicola Iarocci
    CoderDojo
    Coding Clubs for Kids

    View full-size slide

  8. MongoDB & REST APIs
    A Match Made in Heaven

    View full-size slide

  9. Agenda
    1. Our use case for a RESTful API

    View full-size slide

  10. Agenda
    2. What is a RESTful API and why we need it

    View full-size slide

  11. Agenda
    3. Why MongoDB is a good match for RESTful Services

    View full-size slide

  12. Agenda
    4. Build and run a MongoDB RESTful Service from scratch, live on stage.

    View full-size slide

  13. Agenda
    5. Stories from the field (if there’s any time left, which I doubt)

    View full-size slide

  14. The Case
    for RESTful Web APIs

    View full-size slide

  15. Amica 10
    invoicing & accounting for italian small businesses

    View full-size slide

  16. your old school desktop app

    View full-size slide

  17. what we started with
    Client
    LAN/SQL
    Database
    Desktop
    Application

    View full-size slide

  18. Goal
    A remote service that client apps can leverage to stay in sync withc each other

    View full-size slide

  19. What we need #1
    Must be accessible by any kind of client technology

    View full-size slide

  20. What we need #2
    Abstract the data access layer
    so we can update/replace the engine at any time with no impact on clients

    View full-size slide

  21. What we need #3
    An appropriate data storage engine

    View full-size slide

  22. What we need #4
    Easily (re)deployable and scalable multi-micro-service architecure

    View full-size slide

  23. Where we want to go
    Clients
    “Cloud”
    Database
    RESTful
    Web API
    API
    iOS
    Android
    Website
    Desktop Client
    ? ?

    View full-size slide

  24. Constraints
    • minimum viable product first
    • add features over time
    • frequent database schema updates
    • easily scalable
    • avoid downtime as much as possible
    • cater upfront for a microservices architecture

    View full-size slide

  25. REST
    So What Is REST All About?

    View full-size slide

  26. REST is not a standard

    View full-size slide

  27. REST is not a protocol

    View full-size slide

  28. REST is an architectural style
    for networked applications

    View full-size slide

  29. Defines a set of simple principles
    loosely followed by most API implementations

    View full-size slide

  30. “resource”
    the source of a specific information

    View full-size slide

  31. A web page is not a resource
    rather the representation of a resource

    View full-size slide

  32. “global permanent identifier”
    every resource is uniquely identified. Think a HTTP URI.

    View full-size slide

  33. #3
    standard interface
    used to exchange representations of resources
    (think the HTTP protocol)

    View full-size slide

  34. “a set of constraints”
    separation of concerns, stateless, cacheability, layered system, uniform interface, etc.

    View full-size slide

  35. Web is built on REST
    and it is meant to be consumed by humans

    View full-size slide

  36. RESTful APIs are built on REST
    and are meant to be consumed by machines

    View full-size slide

  37. Representational State Transfer (REST)
    by Roy Thomas Fielding
    http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

    View full-size slide

  38. Goals #1 and #2 are met
    REST layer allows all kinds of client technologies and abstracts the data away

    View full-size slide

  39. MongoDB and REST
    Or why we picked MongoDB for our REST API

    View full-size slide

  40. JSON transport
    Most REST services and clients produce and consume use JSON

    View full-size slide

  41. JSON-style data store
    MongoDB stores data as Binary JSON

    View full-size slide

  42. JSON & RESTful API
    JSON
    accepted media type
    Client
    JSON
    (BSON)
    Mongo
    GET
    maybe we can push directly to client?

    View full-size slide

  43. JSON & RESTful API
    JSON
    accepted media type
    Client
    JSON
    (BSON)
    Mongo
    JSON
    subset of python dict
    (kinda)
    API
    GET
    almost.

    View full-size slide

  44. JSON & RESTful API
    JSON
    objects
    Client
    JSON
    (BSON)
    Mongo
    JSON/dict
    maps to python dict
    (validation layer)
    API
    POST
    also works when sending data the database

    View full-size slide

  45. Similarity with RDBMS
    makes NoSQL easy to grasp (even for a sql head like me)

    View full-size slide

  46. Terminology
    RDBMS Mongo
    Database Database
    Table Collection
    Rows(s) JSON Document
    Index Index
    Join Embedding & Linking

    View full-size slide

  47. What about Queries?
    Queries in MongoDB are represented as JSON-style objects
    db.things.find({x: 3, y: "foo”});

    View full-size slide

  48. Filtering and Sorting
    native
    Mongo
    query syntax
    Client
    JSON
    (BSON)
    Mongo
    (very) thin
    parsing
    & validation
    layer
    API
    Expose the native MongoDB syntax?
    ?where={“x”: 3, “y”: “foo”}

    View full-size slide

  49. JSON all along the pipeline
    mapping to and from the database feels more natural

    View full-size slide

  50. No need for ORM
    No need to map objects to JSON and vice-versa (win!)

    View full-size slide

  51. schema-less
    dynamic documents allow for painless evolution

    View full-size slide

  52. REST is stateless
    MongoDB lacks transactions

    View full-size slide

  53. Ideal API Surface
    Mongo collection maps to API resource endpoint
    api.example.com/contacts
    Maps to a Mongo collection

    View full-size slide

  54. Ideal API Surface
    Mongo document maps to a API document endpoint
    api.example.com/contacts/4f46445fc88e201858000000
    Maps to a collection ObjectID

    View full-size slide

  55. Goal #3 is met
    An appropriate data storage engine: MongoDB

    View full-size slide

  56. Eve
    REST API for Humans™
    Free and Open Source
    Powered by MongoDB and Good Intentions
    eve

    View full-size slide

  57. Philosopy
    effortlessly build and deploy highly customizable, fully featured
    RESTful Web Services

    View full-size slide

  58. install
    $ pip install eve

    View full-size slide

  59. run.py
    from eve import Eve
    app = Eve()
    if __name__ == '__main__':
    app.run()

    View full-size slide

  60. settings.py
    # just a couple API endpoints with no custom
    schema or rules.
    DOMAIN = {
    ‘people’: {}
    ‘works’: {}
    }

    View full-size slide

  61. launch
    $ python run.py
    * Running on http://127.0.0.1:5000/

    View full-size slide

  62. enjoy
    HATEOAS AT WORK HERE
    $ curl http://localhost:5000/people
    {
    "_items": [],
    "_links": {
    "self": {"href": "people", "title": "people"},
    "parent": {“href": "/", "title": "home"},
    },
    "_meta": {
    "max_results": 25,
    "total": 0,
    "page": 1
    }}

    View full-size slide

  63. enjoy
    CLIENTS CAN
    EXPLORE THE API
    PROGRAMMATICALLY
    $ curl http://localhost:5000/people
    {
    "_items": [],
    "_links": {
    "self": {"href": "people", "title": "people"},
    "parent": {“href": "/", "title": “home”}
    },
    "_meta": {
    "max_results": 25,
    "total": 0,
    "page": 1
    }}

    View full-size slide

  64. $ curl http://localhost:5000/people
    {
    "_items": [],
    "_links": {
    "self": {"href": "people", "title": "people"},
    "parent": {“href": "/", "title": "home"},
    },
    "_meta": {
    "max_results": 25,
    "total": 0,
    "page": 1
    }}
    enjoy
    AND EVENTUALLY FILL THE UI

    View full-size slide

  65. enjoy
    $ curl http://localhost:5000/people
    {
    "_items": [],
    "_links": {
    "self": {"href": "people", "title": "people"},
    "parent": {“href": "/", "title": "home"},
    },
    "_meta": {
    "max_results": 25,
    "total": 0,
    "page": 1
    }}
    PAGINATION DATA

    View full-size slide

  66. enjoy
    EMTPY RESOURCE
    AS WE DID NOT
    CONNECT A DATASOURCE
    $ curl http://localhost:5000/people
    {
    "_items": [],
    "_links": {
    "self": {"href": "people", "title": "people"},
    "parent": {“href": "/", "title": "home"},
    },
    "_meta": {
    "max_results": 25,
    "total": 0,
    "page": 1
    }}

    View full-size slide

  67. settings.py
    # let’s connect to a mongo instance
    MONGO_HOST = 'localhost'
    MONGO_PORT = 27017
    MONGO_USERNAME = 'user'
    MONGO_PASSWORD = 'user'
    MONGO_DBNAME = 'percona'

    View full-size slide

  68. settings.py
    # let’s also add a few validation rules
    DOMAIN['people']['schema'] = {
    'name': {
    'type': 'string’,
    'maxlength': 50,
    'unique': True},
    'email': {
    'type': 'string',
    'regex': '^\S+@\S+$'},
    'location': {
    'type': 'dict',
    'schema': {
    'address': {'type': 'string'},
    'city': {'type': 'string’}}},
    'born': {'type': 'datetime'}}
    UNIQUE STRING,
    MAX LENGTH 50

    View full-size slide

  69. settings.py
    # let’s also add a few validation rules
    DOMAIN['people']['schema'] = {
    'name': {
    'type': 'string',
    'maxlength': 50,
    'unique': True},
    'email': {
    'type': 'string',
    'regex': '^\S+@\S+$'},
    'location': {
    'type': 'dict',
    'schema': {
    'address': {'type': 'string'},
    'city': {'type': 'string’}}},
    'born': {'type': 'datetime'}}
    ONLY ACCEPT
    VALID EMAILS

    View full-size slide

  70. settings.py
    # let’s also add a few validation rules
    DOMAIN['people']['schema'] = {
    'name': {
    'type': 'string’,
    'maxlength': 50,
    'unique': True},
    'email': {
    'type': 'string',
    'regex': '^\S+@\S+$'},
    'location': {
    'type': 'dict',
    'schema': {
    'address': {'type': 'string'},
    'city': {'type': 'string’}}},
    'born': {'type': 'datetime'}}
    THIS REGEX SUCKS!

    DON’T USE
    IN PRODUCTION

    View full-size slide

  71. settings.py
    # let’s also add a few validation rules
    DOMAIN['people']['schema'] = {
    'name': {
    'type': 'string',
    'maxlength': 50,
    'unique': True},
    'email': {
    'type': 'string',
    'regex': '^\S+@\S+$'},
    'location': {
    'type': 'dict',
    'schema': {
    'address': {'type': 'string'},
    'city': {'type': 'string’}}},
    'born': {'type': 'datetime'}}
    SUBDOCUMENT WITH
    2 STRING FIELDS

    View full-size slide

  72. settings.py
    # let’s also add a few validation rules
    DOMAIN['people']['schema'] = {
    'name': {
    'type': 'string’,
    'maxlength': 50,
    'unique': True},
    'email': {
    'type': 'string',
    'regex': '^\S+@\S+$'},
    'location': {
    'type': 'dict',
    'schema': {
    'address': {'type': 'string'},
    'city': {'type': 'string’}}},
    'born': {'type': 'datetime'}}
    ONLY ACCEPT
    DATETIME VALUES

    View full-size slide

  73. settings.py
    # allow write access to API endpoints
    # (default is [‘GET’] for both settings)
    # /people
    RESOURCE_METHODS = ['GET','POST']
    # /people/
    ITEM_METHODS = ['GET','PATCH','PUT','DELETE']
    ADD/CREATE ONE OR MORE ITEMS

    View full-size slide

  74. settings.py
    # allow write access to API endpoints
    # (default is [‘GET’] for both settings)
    # /people
    RESOURCE_METHODS = ['GET','POST']
    # /people/
    ITEM_METHODS = ['GET','PATCH','PUT','DELETE']
    EDIT ITEM

    View full-size slide

  75. settings.py
    # allow write access to API endpoints
    # (default is [‘GET’] for both settings)
    # /people
    RESOURCE_METHODS = ['GET','POST']
    # /people/
    ITEM_METHODS = ['GET','PATCH','PUT','DELETE']
    REPLACE ITEM

    View full-size slide

  76. settings.py
    # allow write access to API endpoints
    # (default is [‘GET’] for both settings)
    # /people
    RESOURCE_METHODS = ['GET','POST']
    # /people/
    ITEM_METHODS = ['GET','PATCH','PUT','DELETE']
    YOU GUESSED IT

    View full-size slide

  77. settings.py
    CLIENT UI
    # a few optional config options
    DOMAIN['people'].update(
    {
    'item_title': 'person',
    'cache_control':'max-age=10,must-revalidate',
    'cache_expires': 10,
    'additional_lookup': {
    'url’: 'regex("[\w]+")',
    'field’: 'name'}
    }
    }
    )

    View full-size slide

  78. settings.py
    CLIENT CACHE OPTIONS
    # a few optional config options
    DOMAIN['people'].update(
    {
    'item_title': 'person',
    'cache_control':'max-age=10,must-revalidate',
    'cache_expires': 10,
    'additional_lookup': {
    'url’: 'regex("[\w]+")',
    'field’: 'name'}
    }
    }
    )

    View full-size slide

  79. settings.py
    ALTERNATE ENDPOINT
    # a few optional config options
    DOMAIN['people'].update(
    {
    'item_title': 'person',
    'cache_control':'max-age=10,must-revalidate',
    'cache_expires': 10,
    'additional_lookup': {
    'url’: 'regex("[\w]+")',
    'field’: 'name'}
    }
    }
    )

    View full-size slide

  80. Features Overview
    We are going to focus on MongoDB power-ups

    View full-size slide

  81. full range of CRUD operations
    Create/POST
    Read/GET
    Update/PATCH and Replace/PUT
    Delete/DELETE

    View full-size slide

  82. filters, mongo style
    ?where={“name”: “john”}

    View full-size slide

  83. filters, the python way
    ?where=name==john

    View full-size slide

  84. sorting
    ?sort=city,-name
    SORT BY CITY, THEN NAME DESCENDING

    View full-size slide

  85. projections
    ?projection={"avatar": 0}
    RETURN ALL FIELDS BUT ‘AVATAR’

    View full-size slide

  86. projections
    ?projection={"lastname": 1}
    ONLY RETURN ‘LASTNAME’

    View full-size slide

  87. pagination
    ?max_results=20&page=2
    MAX 20 RESULTS PER PAGE; PAGE 2

    View full-size slide

  88. GeoJSON
    support and validation for all GeoJSON types
    Point, LineString, Polygon, MultiPoint,
    MultiLineString, MultiPolygon, GeometricalCollection

    View full-size slide

  89. document embedding
    joins

    View full-size slide

  90. standard request
    $ curl example.com/works/
    {

    "title": "Book Title",

    "description": "book description",

    "author": “52da465a5610320002660f94"

    }
    RAW FOREIGN KEY
    (DEFAULT)

    View full-size slide

  91. request an embedded document
    $ curl example.com/works/?embedded={“author”: 1}
    {

    "title": "Book Title",

    "description": "book description",

    "author": {

    “firstname”: “Mark”,

    “lastname”: “Green”,

    }

    }
    REQUEST EMBEDDED AUTHOR

    View full-size slide

  92. embedded document
    $ curl example.com/works/?embedded={“author”: 1}
    {

    "title": "Book Title",

    "description": "book description",

    "author": {

    “firstname”: “Mark”,

    “lastname”: “Green”,

    }

    }
    # embedding is configurable on per-field basis and
    # can be pre-set by API maintainer
    EMBEDDED DOCUMENT

    View full-size slide

  93. bulk inserts
    insert multiple documents with a single request

    View full-size slide

  94. request
    $ curl -d ‘
    [
    {
    "firstname": "barack",
    "lastname": “obama"
    },
    {
    "firstname": "mitt",
    "lastname": “romney”
    }
    ]'
    -H 'Content-Type: application/json’

    View full-size slide

  95. response
    [
    {
    "_status": "OK",
    "_updated": "Thu, 22 Nov 2012 15:22:27 GMT",
    "_id": "50ae43339fa12500024def5b",
    "_etag": "749093d334ebd05cf7f2b7dbfb7868605578db2c"
    "_links": {"self": {"href": “”, "title": "person"}}
    },
    {
    "_status": "OK",
    "_updated": "Thu, 22 Nov 2012 15:22:27 GMT",
    "_id": "50ae43339fa12500024def5c",
    "_etag": "62d356f623c7d9dc864ffa5facc47dced4ba6907"
    "_links": {"self": {"href": “", "title": "person"}}
    }
    ] COHERENCE MODE OFF: ONLY META FIELDS ARE RETURNED

    View full-size slide

  96. response
    [
    {
    "_status": "OK",
    "_updated": "Thu, 22 Nov 2012 15:22:27 GMT",
    "_id": "50ae43339fa12500024def5b",
    "_etag": "749093d334ebd05cf7f2b7dbfb7868605578db2c"
    "_links": {"self": {"href": “”, "title": “person”}},
    "firstname": "barack",
    "lastname": "obama",
    },
    {
    "_status": "OK",
    "_updated": "Thu, 22 Nov 2012 15:22:27 GMT",
    "_id": "50ae43339fa12500024def5c",
    "_etag": "62d356f623c7d9dc864ffa5facc47dced4ba6907"
    "_links": {"self": {"href": “", "title": "person"}}
    "firstname": "mitt",
    "lastname": "romney",
    }
    ]
    COHERENCE MODE ON: ALL FIELDS RETURNED

    View full-size slide

  97. document versioning
    ?version=3
    ?version=all
    ?version=diffs

    View full-size slide

  98. soft deletes
    preserve deleted documents and retrieve them with a simple
    ?show_deleted

    View full-size slide

  99. file storage
    files are stored in GridFS by default; customizable for S3, file system, etc.

    View full-size slide

  100. data validation
    powerful and extensible data validation powered by Cerberus

    View full-size slide

  101. rich validation grammar
    referentrial integrity / unique values / defaults / regex / etc.

    View full-size slide

  102. custom data types
    create your own data types to validate against

    View full-size slide

  103. custom validation logic
    extended the validation system to cater for specific use cases

    View full-size slide

  104. multi database
    serve endpoints and/or users from dedicated mongos

    View full-size slide

  105. index maintenance
    define sets of resource indexes to be (re)created at launch
    supports sparse, geo2d and background indexes

    View full-size slide

  106. event hooks
    plug custom actions in the request/response cycle

    View full-size slide

  107. run.py
    from eve import Eve
    app = Eve()
    def percona(resource, response):
    documents = response['_items']
    for document in documents:
    document['percona'] = 'is so cool!'
    if __name__ == '__main__':
    app.on_fetched_resource += percona_live
    app.run()
    CALLBACK FUNCTION

    View full-size slide

  108. run.py
    from eve import Eve
    app = Eve()
    def percona(resource, response):
    documents = response['_items']
    for document in documents:
    document['percona'] = 'is so cool!'
    if __name__ == '__main__':
    app.on_fetched_resource += percona_live
    app.run()
    LOOP ON ALL DOCUMENTS

    View full-size slide

  109. run.py
    from eve import Eve
    app = Eve()
    def percona(resource, response):
    documents = response['_items']
    for document in documents:
    document['percona'] = 'is so cool!'
    if __name__ == '__main__':
    app.on_fetched_resource += percona_live
    app.run()
    INJIECT FIELD

    View full-size slide

  110. run.py
    from eve import Eve
    app = Eve()
    def percona(resource, response):
    documents = response['_items']
    for document in documents:
    document['percona'] = 'is so cool!'
    if __name__ == '__main__':
    app.on_fetched_resource += percona_live
    app.run()
    ATTACH CALLBACK TO
    EVENT HOOK

    View full-size slide

  111. rate limiting
    powered

    View full-size slide

  112. settings.py
    # Rate limit on GET requests:
    RATE_LIMIT_GET = (1, 60)
    ONE REQUEST PER MINUTE (CLIENT)

    View full-size slide

  113. $ curl -i
    HTTP/1.1 200 OK
    X-RateLimit-Limit: 1
    X-RateLimit-Remaining: 0
    X-RateLimit-Reset: 1390486659
    rate limited request
    CURRENT LIMIT

    View full-size slide

  114. $ curl -i
    HTTP/1.1 200 OK
    X-RateLimit-Limit: 1
    X-RateLimit-Remaining: 0
    X-RateLimit-Reset: 1390486659
    rate limited request
    REMAINING

    View full-size slide

  115. $ curl -i
    HTTP/1.1 200 OK
    X-RateLimit-Limit: 1
    X-RateLimit-Remaining: 0
    X-RateLimit-Reset: 1390486659
    rate limited request
    TIME TO RESET

    View full-size slide

  116. $ curl -i
    HTTP/1.1 429 TOO MANY REQUESTS
    rate limited request
    OUCH!

    View full-size slide

  117. operations log
    log all operations and eventually expose a dedicated endpoint

    View full-size slide

  118. HATEOAS
    Hypermedia As Engine Of The Application State

    View full-size slide

  119. XML support
    $ curl -H ”Accept: application/xml” -i http://example.com/people



    <_created>Fri, 18 Sep 2015 13:41:37 GMT
    <_etag>5d057712ce792ebb4100b96aa98bfe9b6693c07b
    <_id>55fc149138345b0880f07e3d
    <_updated>Fri, 18 Sep 2015 13:41:37 GMT
    [email protected]
    john


    View full-size slide

  120. conditional requests
    allow clients to only request non-cached content

    View full-size slide

  121. If-Modified-Since
    If-Modified-Since: Wed, 05 Dec 2012 09:53:07 GMT
    ONLY RETURN DOCUMENT IF MODIFIED SINCE

    View full-size slide

  122. If-None-Match
    If-None-Match:1234567890123456789012345678901234567890
    >
    ONLY RETURN DOCUMENT ETAG CHANGED

    View full-size slide

  123. data integrity and concurrency
    no overwriting documents with obsolete versions

    View full-size slide

  124. missing ETag
    # fails, as there is no ETag included with request
    $ curl \
    -X PATCH \
    -i http://example.com/people/521d6840c437dc0002d1203c \
    -H "Content-Type: application/json" \
    -d '{"name": “ronald"}'
    HTTP/1.1 403 FORBIDDEN
    NO ETAG
    REJECTED

    View full-size slide

  125. ETag mismatch
    # fails, as ETag does not match with server
    $ curl \
    -X PATCH \
    -i http://example.com/people/521d6840c437dc0002d1203c \
    -H "If-Match: 1234567890123456789012345678901234567890" \
    -H "Content-Type: application/json” \
    -d '{"firstname": "ronald"}'
    HTTP/1.1 412 PRECONDITION FAILED
    ETAG MISMATCH
    REJECTED

    View full-size slide

  126. valid ETag
    # success at last! ETag matches with server
    $ curl \
    -X PATCH \
    -i http://example.com/people/50adfa4038345b1049c88a37 \
    -H "If-Match: 80b81f314712932a4d4ea75ab0b76a4eea613012" \
    -H "Content-Type: application/json" \
    -d '{"firstname": "ronald"}'
    HTTP/1.1 200 OK
    # Like most of features, ETags can be disabled.
    ETAG MATCH
    ACCEPTED

    View full-size slide

  127. custom data layers
    build your own data layer

    View full-size slide

  128. authentication and authorization
    basic / token / hmac / BYO / OAuth2 / you name it

    View full-size slide

  129. and (a lot) more
    CORS, cache control, API versioning, JOSNP, Etc.

    View full-size slide

  130. vibrant community
    90+ contributors / 350+ forks / 2500+ github stargazers

    View full-size slide

  131. Eve-Docs
    automatic documentation for Eve APIs in both HTML and JSON
    CHARLES FLYNN

    View full-size slide

  132. Eve-Elastic
    Elasticsearch data layer for your Eve-powered API
    PETR JASEK

    View full-size slide

  133. Eve-SQLAlchemy
    SQL data layer for Eve-powered APIs
    PETR JASEK

    View full-size slide

  134. Eve-Mongoengine
    enables mongoengines data models to be used as Eve schema
    STANISLAV HELLER

    View full-size slide

  135. Eve.NET
    HTTP and REST client for Eve-powered APIs
    PETR JASEK

    View full-size slide

  136. Eve-OAuth2
    leverage Flask-Sentinel to protect your API endpoints with OAuth2
    THOMAS SILEO

    View full-size slide

  137. REST Layer
    “golang REST API framework heavily inspired by Python Eve”
    THOMAS SILEO

    View full-size slide

  138. Goal # 4 achieved
    easy to setup, launch and scale up; also a good fit for microservices infrastracture

    View full-size slide

  139. A look back to initial draft
    Clients
    “Cloud”
    Database
    RESTful
    Web API
    API
    iOS
    Android
    Website
    Desktop Client
    ? ?

    View full-size slide

  140. Clients
    Multiple
    MongoDBs
    Database
    Adam
    eve instances
    API
    iOS
    Android
    Website
    Desktop Client
    what we have in production

    View full-size slide

  141. stories from the trenches
    #1. when too much (magic) is too much
    #2. sometimes you don’t want to debug
    #3. so how do I login into this thing?

    View full-size slide

  142. Enhance MongoDB
    with powerful features on top of native engine
    validation, document embedding (joins), referential integrity,
    document versioning, transformations, rate limiting, etc.

    View full-size slide

  143. Consider the REST layer
    as an ideal data access layer
    the story of pymongo 3.0 breaking changes
    mongo or sql or elastic or …

    View full-size slide

  144. Consider the REST layer
    as an ideal data access layer
    the story of Adam dashboards

    View full-size slide

  145. Consider Microservices
    leverage Eve features create a network of isolated yet standardized services

    each service has a dedicated role
    runs as an eve instance, with its own configuration
    has its own database(s)
    callbacks route traffic between services

    View full-size slide

  146. Clients
    User-reserved
    MongoDBs
    eve-multidb
    Data
    Auth
    eve-oauth2
    (flask-sentinel)
    API
    iOS
    Android
    Website
    Desktop Client
    Adam 1
    Adam
    eve instance
    Redis
    auth tokens,
    rate limiting
    Auth/Users
    MongoDB

    View full-size slide

  147. Clients
    service-
    reserved
    MongoDBs
    Data
    Auth
    eve-oauth2,
    flask-sentinel
    API
    iOS
    Android
    Website
    Desktop Client
    Adam 2
    Adam
    eve instance
    Redis
    auth tokens,
    rate limiting
    Services
    eve instances
    Auth/Users
    MongoDB
    very simplified

    View full-size slide

  148. thanks
    nicolaiarocci
    python-eve.org
    eve

    View full-size slide