MongoAtlas Metrics understanding

I have AWS Lambdas connecting to MongoAtlas serverless instance to run a simple findById query in one collection which contains only one record. I’m already reusing the Mongo connection across Lambdas as recommended but once I started a small load tests performance, I’m seeing the number of connections increasing on MongoAtlas Metrics and then the query is taking too much time to execute which results in Lambda timeouts (6s).

I want to better understand the metrics, mainly the Read Units capacity because I’m reaching around 100K of read units during load tests and want to know what is the limit for Mongo.

Some results:
Execution Time (Average command operational latency): 2.6s
High peak of connections: around 450
Network (num of requests): around 283/s

Note 1) I have index configured on the collection.
Note 2) I’m not connecting to MongoAtlas through PrivateLink, I’m using AWS Nat Gateway for that. Wondering if PrivateLink could improve my test performance.

Could you please help me understanding if these metrics explain my issue?

Metrics:


Hi @Thiago_Scodeler,

I am curious about the following:

I have AWS Lambdas connecting to MongoAtlas serverless instance to run a simple findById query in one collection which contains only one record.

Just to clarify, the findById, I presume you mean the mongoose function Model.findById(). Please correct me if I am wrong here. It seems this returns only a singular document :

Finds a single document by its _id field.

Can you confirm:

  1. The collection where this operation is run on only contains 1 document
  2. The operation using findById returns the same document in 1. above
  3. The size of the document in the collection

but once I started a small load tests performance

Can you provide more details regarding the load tests being performed?

In terms of the connection peak, based off the information provided, the Serverless instances can support up to 500 simultaneous connections as of the time of this message. More information on the Serverless - Operational Limitations and Considerations page.

I’m seeing the number of connections increasing on MongoAtlas Metrics and then the query is taking too much time to execute which results in Lambda timeouts (6s).

Have you tried altering the timeout to see whether the number of connections recorded increases?

I want to better understand the metrics, mainly the Read Units capacity because I’m reaching around 100K of read units during load tests and want to know what is the limit for Mongo.

Regarding the Serverless Instance metrics, you may wish to review the Review Serverless Metrics page for more information on the available metrics. However, in saying so, you can also view detailed information on the specific values recorded on the metrics charts by going to the metrics page and selecting the information button i as shown in the below example for the Connections metric:

I do not believe there is a hardcoded upper limit value regarding the Read Units. You can review the following documentation for more information regarding Read Units and it’s pricing:

Note 1) I have index configured on the collection.

Can you provide the following details:

  1. The full findById operation being used
  2. Output of db.collection.getIndexes()
  3. The output of .explain("executionStats") for the findById operation

In the meantime, you may also wish to review the Manage Connections with AWS Lambda documentation as well.

Regards,
Jason

Hi @Jason_Tran thanks for replying.

Yes, your assumption about mongoose findById is correct.

  1. The collection where this operation is run on only contains 1 document
    Yes

  2. The operation using findById returns the same document in 1. above
    Yes

  3. The size of the document in the collection
    Very simple json:


{
_id: ObjectId("6359c4a3783fe200522d4c44"),
abcd: 'AAAAA',
type: 'game',
description: 'description',
image: 'image',
productUrl: 'productURL',
tags: [],
active: false,
createdAt: ISODate("2022-10-26T23:37:07.300Z"),
updatedAt: ISODate("2022-10-26T23:37:07.300Z"),
__v: 0
}
  1. The full findById operation being used
    db.products.find({_id: ObjectId(‘6359cfa63e858ad8d44b1780’)});

  2. Output of db.collection.getIndexes()

[ { v: 2, key: { _id: 1 }, name: '_id_' } ]
  1. The output of .explain(“executionStats”) for the findById operation
{
  explainVersion: '1',
  queryPlanner: {
    namespace: 'dev.products',
    indexFilterSet: false,
    parsedQuery: { _id: { '$eq': ObjectId("6359cfa63e858ad8d44b1780") } },
    queryHash: '740C02B0',
    planCacheKey: 'E351FFEC',
    maxIndexedOrSolutionsReached: false,
    maxIndexedAndSolutionsReached: false,
    maxScansToExplodeReached: false,
    winningPlan: { stage: 'IDHACK' },
    rejectedPlans: []
  },

  executionStats: {
    executionSuccess: true,
    nReturned: 1,
    executionTimeMillis: 0,
    totalKeysExamined: 1,
    totalDocsExamined: 1,
    executionStages: {
      stage: 'IDHACK',
      nReturned: 1,
      executionTimeMillisEstimate: 0,
      works: 2,
      advanced: 1,
      needTime: 0,
      needYield: 0,
      saveState: 0,
      restoreState: 0,
      isEOF: 1,
      keysExamined: 1,
      docsExamined: 1
    }
  },
  command: {
    find: 'products',
    filter: { _id: ObjectId("6359cfa63e858ad8d44b1780") },
    '$db': 'dev'
  },
  serverInfo: {
    host: 'serverlessinstance.abcde.mongodb.net',
    port: 27017,
    version: '6.1.0',
    gitVersion: ''
  },
  serverParameters: {
    internalQueryFacetBufferSizeBytes: 104857600,
    internalQueryFacetMaxOutputDocSizeBytes: 104857600,
    internalLookupStageIntermediateDocumentMaxSizeBytes: 16793600,
    internalDocumentSourceGroupMaxMemoryBytes: 104857600,
    internalQueryMaxBlockingSortMemoryUsageBytes: 33554432,
    internalQueryProhibitBlockingMergeOnMongoS: 0,
    internalQueryMaxAddToSetBytes: 104857600,
    internalDocumentSourceSetWindowFieldsMaxMemoryBytes: 104857600
  },
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1666884172, i: 14 }),
    signature: {
      hash: Binary(Buffer.from("", "hex"), 0),
      keyId: Long("")
    }
  },
  operationTime: Timestamp({ t: 1666884172, i: 13 })
}

By increasing the lambda timeout I got the same behavior.

Can you provide more details regarding the load tests being performed?
I’m using [artillery.io] Artillery to run a couple of requests to a API which goes to a lambda connecting to MongoAtlas.
Getting the issue once I reach around 20req/s for a period of 20s. 400 requests in total.

Thanks for providing those details Thiago.

Just to clarify - Is your issue specific to performance, pricing or both? Or is it specific to the lambda timeouts being experienced during the load testing.

Could you share more details of the load testing and what the goals of it are? Is this to flood the database with as much work as possible or is it simulation of expected workload in future?

Lastly, is the ultimate goal to select between serverless or a shared (M2/M5) or dedicated instances (M10+) to see which will suit your workload?

Regards,
Jason

Hi @Jason_Tran

My issue is specific to performance since queries and connections to Mongo Atlas are taking too much time when there a bunch of connections ongoing.

My load test goals is to have the amount of requests my API (lambda) is able to handle during high peaks of usage. Basically the load test runs around 400 to 700 req/s for a period of time (5 minutes for instance) . This is the expected workload for the future.

I already tested with serverless and dedicated instance (M30) and in both instances I got the same behavior (slow queries and slow new connections) when reaching too many connections to the database.