Skip to content

feat(firestore): Add support for 16MB documents#10078

Open
dlarocque wants to merge 6 commits into
mainfrom
dl/large-doc
Open

feat(firestore): Add support for 16MB documents#10078
dlarocque wants to merge 6 commits into
mainfrom
dl/large-doc

Conversation

@dlarocque

@dlarocque dlarocque commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Adds support for 16 MB documents.

  • Increases gPRC message size limit to 17MB from the 4MB default
  • Adds tests that use a seeded database with large documents. These tests can only be ran if FIRESTORE_RUN_LARGE_DOC_TESTS = true. We don't want to run these tests in the default test suite since they are too slow.

Notes:

  • gRPC changes are only relevant for Node bundle
  • WebChannel works out of the box in my testing
  • This PR does not change the flow control window size for Node

We can merge these tests for now. A future task is to have these tests not rely on a seeded database, once large doc writes on watch are working.

@dlarocque dlarocque requested a review from wu-hui June 15, 2026 16:25
@dlarocque dlarocque requested review from a team as code owners June 15, 2026 16:25
@changeset-bot

changeset-bot Bot commented Jun 15, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 4cbfebb

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request configures gRPC connections to support sending and receiving messages up to 17MB and introduces integration tests for handling large documents (up to 15.9MB). It also updates the default project ID resolution in tests. Feedback on these changes includes: (1) ensuring that emulator project ID resolution takes precedence over other environment variables to prevent breaking local emulator testing, (2) refactoring the oversized payload test to avoid catching the manually thrown error, which obscures the assertion failure, and (3) using a beforeEach hook to set the test timeout globally instead of duplicating it across every test case.

Comment on lines +129 to +134
export const DEFAULT_PROJECT_ID =
process.env.FIRESTORE_PROJECT_ID ||
process.env.GCLOUD_PROJECT ||
(USE_EMULATOR
? process.env.FIRESTORE_EMULATOR_PROJECT_ID || 'test-emulator'
: PROJECT_CONFIG.projectId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Prioritizing process.env.GCLOUD_PROJECT or process.env.FIRESTORE_PROJECT_ID over USE_EMULATOR will break local emulator testing if those environment variables are set in the developer's environment (which is very common when using the Google Cloud SDK). When USE_EMULATOR is true, we should always default to the emulator project ID.

export const DEFAULT_PROJECT_ID = USE_EMULATOR
  ? process.env.FIRESTORE_EMULATOR_PROJECT_ID || 'test-emulator'
  : process.env.FIRESTORE_PROJECT_ID ||
    process.env.GCLOUD_PROJECT ||
    PROJECT_CONFIG.projectId;

Comment on lines +209 to +217
try {
await setDoc(docRef, { chunk: largePayload });
throw new Error(
'Setting a document exceeding the 16MB limit should fail.'
);
} catch (error: any) {
console.error('Caught error in oversized payloads:', error);
expect(error.code).to.equal('invalid-argument');
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If setDoc unexpectedly succeeds, the throw new Error(...) will be caught by the catch block, and the assertion expect(error.code).to.equal('invalid-argument') will fail with a confusing error message (expected undefined to equal 'invalid-argument') instead of the intended failure message. Capturing the error and asserting on it outside the try-catch block ensures a clear and correct failure message.

      let error: any;
      try {
        await setDoc(docRef, { chunk: largePayload });
      } catch (e) {
        error = e;
      }
      expect(error, 'Setting a document exceeding the 16MB limit should fail.').to.exist;
      expect(error.code).to.equal('invalid-argument');

Comment on lines +45 to +57
before(function () {
this.timeout(120000); // Tests are very slow because large doc reads have very high latency.
const runLargeTests = process.env.FIRESTORE_RUN_LARGE_DOC_TESTS;
if (runLargeTests !== 'YES' && runLargeTests !== 'true') {
this.skip();
}
if (
getTargetBackend() !== TargetBackend.NIGHTLY ||
!getRunEnterpriseTests()
) {
this.skip();
}
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Calling this.timeout(120000) inside the before hook only sets the timeout for the before hook itself, not for the individual it tests. This is why this.timeout(120000) had to be repeated in every single it block. Using a beforeEach hook to set the timeout for all tests in the suite allows removing the duplicate this.timeout(120000) calls from all it blocks.

  beforeEach(function () {
    this.timeout(120000); // Tests are very slow because large doc reads have very high latency.
  });

  before(function () {
    const runLargeTests = process.env.FIRESTORE_RUN_LARGE_DOC_TESTS;
    if (runLargeTests !== 'YES' && runLargeTests !== 'true') {
      this.skip();
    }
    if (
      getTargetBackend() !== TargetBackend.NIGHTLY ||
      !getRunEnterpriseTests()
    ) {
      this.skip();
    }
  });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense?

Comment on lines +45 to +57
before(function () {
this.timeout(120000); // Tests are very slow because large doc reads have very high latency.
const runLargeTests = process.env.FIRESTORE_RUN_LARGE_DOC_TESTS;
if (runLargeTests !== 'YES' && runLargeTests !== 'true') {
this.skip();
}
if (
getTargetBackend() !== TargetBackend.NIGHTLY ||
!getRunEnterpriseTests()
) {
this.skip();
}
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants