<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Meteor</title>
    <description>The latest articles on Forem by Meteor (@meteor).</description>
    <link>https://forem.com/meteor</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F7631%2F26544787-1db4-4cb3-b6ba-3c2d5427e42a.jpeg</url>
      <title>Forem: Meteor</title>
      <link>https://forem.com/meteor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/meteor"/>
    <language>en</language>
    <item>
      <title>Faster Server Startup in Meteor 3.4 with Deferrables</title>
      <dc:creator>Gabriel Grubba</dc:creator>
      <pubDate>Thu, 12 Feb 2026 22:01:43 +0000</pubDate>
      <link>https://forem.com/meteor/faster-server-startup-in-meteor-34-with-deferrables-46kn</link>
      <guid>https://forem.com/meteor/faster-server-startup-in-meteor-34-with-deferrables-46kn</guid>
      <description>&lt;p&gt;As you might have seen in the &lt;a href="https://dev.to/meteor/meteor-34-is-out-rspack-integration-4x-faster-builds-8x-smaller-bundles-and-extended-bundler-51ia"&gt;3.4 release blog post&lt;/a&gt;, Meteor has received a &lt;strong&gt;HUGE&lt;/strong&gt; update with a lot of focus on the developer experience. One of the new additions was the new &lt;code&gt;deferrable&lt;/code&gt; functions, which we will dive into today in this blog post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why were those functions added?
&lt;/h2&gt;

&lt;p&gt;While seeing teams update to 3.4, we saw a recurring problem: build times have gotten faster with rspack, but the developers were not feeling it because they had a bottleneck at the &lt;strong&gt;startup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With that in mind, we did our investigation, and we saw that those apps that were not feeling this increase in productivity were the ones that had async or costly operations being done at the startup. You can think of requesting data from external APIs, waiting for sidekick services to get started, etc.&lt;/p&gt;

&lt;p&gt;For production, this makes sense — you don’t want your app to start without those dependencies ready. You might not need all that. With that in mind, we made this addition to our api.&lt;/p&gt;

&lt;h2&gt;
  
  
  New API
&lt;/h2&gt;

&lt;p&gt;The added functions were: &lt;a href="https://docs.meteor.com/api/meteor.html#Meteor-deferrable" rel="noopener noreferrer"&gt;&lt;code&gt;deferrable&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://docs.meteor.com/api/meteor.html#Meteor-deferDev" rel="noopener noreferrer"&gt;&lt;code&gt;deferDev&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://docs.meteor.com/api/meteor.html#Meteor-deferProd" rel="noopener noreferrer"&gt;&lt;code&gt;deferProd&lt;/code&gt;&lt;/a&gt;. I'll start with the first.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️&lt;br&gt;
If a function is not deferred for the current environment, it runs immediately and behaves exactly like a normal function call (including return values).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Meteor.deferrable
&lt;/h3&gt;

&lt;p&gt;In the docs, we can see it in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Meteor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;meteor/meteor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;Meteor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Meteor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deferrable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;connectToExternalDB&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;development&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that, &lt;code&gt;on&lt;/code&gt; development, this connectToExternalDB function will run deferred (scheduled to run after the initial startup completes, instead of blocking it).&lt;/p&gt;

&lt;p&gt;You can define &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;development&lt;/code&gt;, and &lt;code&gt;production&lt;/code&gt; – for testing only environments, this can be very nice! &lt;/p&gt;

&lt;p&gt;Conceptually, deferrable functions let Meteor finish booting the app first, and then run non-critical async work afterward. The app becomes usable sooner, even if some background initialization is still happening.&lt;/p&gt;

&lt;h4&gt;
  
  
  Meteor.deferDev
&lt;/h4&gt;

&lt;p&gt;deferDev is an abstraction on top of &lt;code&gt;deferrable&lt;/code&gt; with the options for development and testing environments.&lt;/p&gt;

&lt;p&gt;This is probably the one that will be used the most. You should use this one for flagging those functions that &lt;em&gt;can&lt;/em&gt; run later in development mode; Consistently using it will make your overall startup and rebuild faster. &lt;/p&gt;

&lt;p&gt;In our hypothetical &lt;a href="https://github.com/Grubba27/modern-meteor-example/pull/1" rel="noopener noreferrer"&gt;PR&lt;/a&gt; example, using &lt;code&gt;deferDev&lt;/code&gt; was saving our startup time in around two seconds!&lt;/p&gt;

&lt;p&gt;And to use it is &lt;em&gt;very&lt;/em&gt; simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const connectToExternalExpensiveService = async () =&amp;gt; {
    const sleep = (ms) =&amp;gt; new Promise(resolve =&amp;gt; setTimeout(resolve, ms));
    console.log("Connecting to external expensive service...");
    await sleep(Math.random() * 2000 + 1000); // simulate expensive connection
    console.log("Connected to external expensive service!");
  }

  await Meteor.deferDev(connectToExternalExpensiveService);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Meteor.deferProd
&lt;/h4&gt;

&lt;p&gt;deferProd is an abstraction on top of &lt;code&gt;deferrable&lt;/code&gt; with the options for production.&lt;/p&gt;

&lt;p&gt;This is used for more one-off cases. We saw usage in this one for connecting to dev-only services and to overall services that will be used later in production, but were necessary to be there at startup when working locally.&lt;/p&gt;

&lt;p&gt;A good example is warming a cache or connecting to an analytics pipeline that won’t be used during the first requests, but must still exist in production.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using deferrable with values
&lt;/h4&gt;

&lt;p&gt;The last notable thing about this new API is that deferred functions, if they are not deferred they, work &lt;em&gt;exactly&lt;/em&gt; as if they were not marked as deferred.&lt;/p&gt;

&lt;p&gt;You can see this logging example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Before defer Dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;Meteor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deferDev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connecting to some external service...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This will run later on local mode!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;After defer Dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Before defer Prod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;Meteor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deferProd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connecting to some service...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This will run later on prod mode!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;After defer Prod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// in a regular meteor run&lt;/span&gt;
  &lt;span class="c1"&gt;// Before defer Dev&lt;/span&gt;
  &lt;span class="c1"&gt;// After defer Dev&lt;/span&gt;
  &lt;span class="c1"&gt;// Before defer Prod&lt;/span&gt;
  &lt;span class="c1"&gt;// Connecting to some service...&lt;/span&gt;
  &lt;span class="c1"&gt;// This will run later on prod mode!&lt;/span&gt;
  &lt;span class="c1"&gt;// After defer Prod&lt;/span&gt;
  &lt;span class="c1"&gt;// Connecting to some external service...&lt;/span&gt;
  &lt;span class="c1"&gt;// This will run later on local mode!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Very cool, eh?&lt;/p&gt;

&lt;p&gt;But &lt;em&gt;also&lt;/em&gt; this API can return values so for example you can have this example in your code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Meteor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deferDev&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;later_in_dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;Meteor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deferProd&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;later_in_prod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value is set to:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a function is not deferred for the current environment, it runs immediately and behaves exactly like a normal function call (including return values).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️&lt;br&gt;
You can see all the examples that I shared today in this &lt;a href="https://github.com/Grubba27/modern-meteor-example/pull/1" rel="noopener noreferrer"&gt;PR&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Migration &amp;amp; Conclusion
&lt;/h3&gt;

&lt;p&gt;To start getting gains with this new API, begin by wrapping your slowest startup work — external connections, async setup, or non-critical initialization — with &lt;code&gt;deferDev&lt;/code&gt; and measure the impact. Most teams will see improvements immediately.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://galaxycloud.app/" rel="noopener noreferrer"&gt;Galaxy team&lt;/a&gt; saw these improvements first hand – their local environment, with these optimizations, got ~3x faster!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can think of these functions as saying: &lt;code&gt;this work is important — just not right now.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Treat &lt;code&gt;deferDev&lt;/code&gt; as part of your startup hygiene: anything that doesn’t block correctness should be a candidate.&lt;/p&gt;

&lt;p&gt;If you haven’t revisited your startup code since upgrading to 3.4, now is the perfect time — you may be sitting on seconds of free productivity without realizing it.&lt;/p&gt;

&lt;p&gt;If you’re migrating to 3.4 and have questions, run into edge cases, or want to share how much startup time you shaved off using these APIs, join the conversation on the Meteor forums. We’d love to hear what worked for your app — and what didn’t.&lt;/p&gt;




&lt;p&gt;We’re excited about what’s to come and can’t wait for you to join the Meteor renaissance!&lt;/p&gt;

&lt;p&gt;For feedback, questions, or support, &lt;a href="https://forums.meteor.com/" rel="noopener noreferrer"&gt;visit our forums&lt;/a&gt; or join our &lt;a href="https://discord.com/invite/3w7EKdpghq" rel="noopener noreferrer"&gt;Discord channel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Follow us on &lt;a href="https://x.com/meteorjs" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://github.com/meteor" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>meteor</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Meteor 3.4 is out: Rspack integration, 4x faster builds, 8x smaller bundles, and extended bundler features</title>
      <dc:creator>Nacho Codoñer</dc:creator>
      <pubDate>Fri, 30 Jan 2026 15:35:58 +0000</pubDate>
      <link>https://forem.com/meteor/meteor-34-is-out-rspack-integration-4x-faster-builds-8x-smaller-bundles-and-extended-bundler-51ia</link>
      <guid>https://forem.com/meteor/meteor-34-is-out-rspack-integration-4x-faster-builds-8x-smaller-bundles-and-extended-bundler-51ia</guid>
      <description>&lt;p&gt;Meteor 3.4 marks the final day of the &lt;strong&gt;&lt;a href="https://galaxycloud.app/galaxy-expansion" rel="noopener noreferrer"&gt;Galaxy Expansion&lt;/a&gt;&lt;/strong&gt; and celebrates a new era for the framework that started it all, bringing modern tools into the core Meteor experience.&lt;/p&gt;

&lt;p&gt;Meteor 3.4 introduces the &lt;strong&gt;Rspack bundler&lt;/strong&gt; in the core to improve the dev experience by cutting build times, reducing bundler size, and supporting standard configuration patterns and features from the wider JS ecosystem.&lt;/p&gt;

&lt;p&gt;This is a big step forward to address many long-requested improvements Meteor users have talked about, and we moved toward them across the newer Meteor 3 era.&lt;/p&gt;

&lt;p&gt;In Meteor 3.2, we started by &lt;a href="https://dev.to/meteor/unlocking-meteor-32-new-profiling-tool-to-track-bundler-performance-and-size-1jc8"&gt;adding tools to monitor our goals for the build experience&lt;/a&gt;, with &lt;code&gt;meteor profile&lt;/code&gt; introduced to measure build times and bundle size.&lt;/p&gt;

&lt;p&gt;In Meteor 3.3, we delivered the &lt;a href="https://dev.to/meteor/faster-builds-in-meteor-33-modern-build-stack-with-swc-and-bundler-optimizations-fm2"&gt;first round of optimizations for faster builds on the Meteor bundler&lt;/a&gt;, getting more from the solid and mature mechanism used for Meteor apps since the beginning. We added a new transpiler with SWC, a new watcher, and other improvements.&lt;/p&gt;

&lt;p&gt;In Meteor 3.4, to wrap up this effort on improving the bundler experience, we focused on delegating to a modern tool like Rspack, which let us meet all initial goals and allow Meteor apps to apply efficient HMR, tree shaking, full ESM support, modern plugins, and more.&lt;/p&gt;

&lt;p&gt;Our core team has already migrated to Rspack for the &lt;a href="https://galaxycloud.app/" rel="noopener noreferrer"&gt;Galaxy Cloud app&lt;/a&gt;, showing the optimizations applied to a real-world app like the one hosting your Meteor apps. This post details the changes and shows the Galaxy app’s improvement metrics as an example of what to expect with your Meteor 3.4 upgrade when adopting the Meteor Rspack integration.&lt;/p&gt;

&lt;p&gt;This release also includes community contributions for Meteor React packages by improving stability and performance of suspense hooks, integrating &lt;code&gt;collection-extensions&lt;/code&gt; package into core, considering Cordova as a modern build, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;To start using Meteor 3.4.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a New App
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create a new Meteor app using Meteor 3.4
meteor create my-app --release 3.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;All improvements introduced in Meteor 3.3 and 3.4, including the Rspack integration, are enabled by default for new apps and applied to all skeleton examples. Check &lt;code&gt;meteor create --help&lt;/code&gt; to see the available skeletons.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Update Your App
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Update your existing Meteor app to version 3.4
meteor update --release 3.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add &lt;code&gt;modern&lt;/code&gt; to your &lt;code&gt;package.json&lt;/code&gt; to enable the Meteor Bundler optimizations:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"meteor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"modern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out &lt;a href="https://docs.meteor.com/about/modern-build-stack/meteor-bundler-optimizations.html#requirements" rel="noopener noreferrer"&gt;the requirements&lt;/a&gt; for Meteor Bundler optimizations on existing apps.&lt;/p&gt;

&lt;h4&gt;
  
  
  ☄️&lt;a href="https://docs.meteor.com/about/modern-build-stack/meteor-bundler-optimizations.html" rel="noopener noreferrer"&gt;Meteor Bundler optimizations docs&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Add &lt;code&gt;rspack&lt;/code&gt; package to enable the Rspack Bundler integration:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;meteor add rspack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out &lt;a href="https://docs.meteor.com/about/modern-build-stack/rspack-bundler-integration.html#requirements" rel="noopener noreferrer"&gt;the requirements&lt;/a&gt; for Rspack Bundler integration on existing apps.&lt;/p&gt;

&lt;h4&gt;
  
  
  ⚡&lt;a href="https://docs.meteor.com/about/modern-build-stack/rspack-bundler-integration.html" rel="noopener noreferrer"&gt;Rspack Bundler integration docs&lt;/a&gt;
&lt;/h4&gt;




&lt;h2&gt;
  
  
  Highlights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Faster Builds
&lt;/h3&gt;

&lt;p&gt;Meteor 3.4 goes further than Meteor 3.3 and the initial SWC adoption. With Rspack now compiling your app code, you get the speed of this modern tool built in Rust. The Meteor bundler still compiles Atmosphere packages and links the final app code, but that part was already optimized in Meteor 3.3, so you get the best of both.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;meteor profile&lt;/code&gt;, &lt;strong&gt;build times drop ~70% and are over ~3.5x faster&lt;/strong&gt;. Rebuild times for both client and server are now much shorter, making development far quicker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.galaxycloud.app%2Fwp-content%2Fuploads%2F2026%2F01%2Ffaster-builds-1.png" class="article-body-image-wrapper"&gt;&lt;img alt="Image" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.galaxycloud.app%2Fwp-content%2Fuploads%2F2026%2F01%2Ffaster-builds-1.png" width="713" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These metrics were measured for the &lt;a href="https://galaxycloud.app/" rel="noopener noreferrer"&gt;Galaxy app&lt;/a&gt; Rspack migration, coming from Meteor 3.3 applied optimizations. Your app will see similar improvements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smaller Bundles
&lt;/h3&gt;

&lt;p&gt;Meteor 3.4 introduces one of the most awaited features to keep app bundles small: &lt;strong&gt;tree shaking&lt;/strong&gt;. With the Meteor-Rspack integration, bundle size is significantly reduced through this built-in optimization, along with other Rspack strategies such as chunk splitting, dynamic imports, minification and more.&lt;/p&gt;

&lt;p&gt;After migrating and deploying the &lt;a href="https://galaxycloud.app/" rel="noopener noreferrer"&gt;Galaxy app&lt;/a&gt;, the &lt;strong&gt;main client bundle size dropped by about 88%&lt;/strong&gt; compared to previous 3.3.2 release. &lt;strong&gt;Client bundles are now thinner&lt;/strong&gt;, meaning &lt;strong&gt;less code delivered&lt;/strong&gt; and &lt;strong&gt;faster initial load times&lt;/strong&gt; for your apps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.galaxycloud.app%2Fwp-content%2Fuploads%2F2026%2F01%2Fsmaller-bundles.png" class="article-body-image-wrapper"&gt;&lt;img alt="image" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.galaxycloud.app%2Fwp-content%2Fuploads%2F2026%2F01%2Fsmaller-bundles.png" width="684" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The gains vary by app, its dependencies, and the optimizations used. Just by applying tree shaking you will get improvements; sometimes smaller, sometimes much larger, depending on how tree-shakeable your dependencies are.&lt;/p&gt;

&lt;p&gt;Additionally, &lt;a href="https://rspack.rs/guide/optimization/code-splitting" rel="noopener noreferrer"&gt;by using code splitting and dynamic imports&lt;/a&gt; you split the main chunk, reduce the main size, and load other pieces on demand. Give it a try and play with these options in your project.&lt;/p&gt;

&lt;h4&gt;
  
  
  Atmosphere Bundle Reduction
&lt;/h4&gt;

&lt;p&gt;What is more, Meteor 3.4 adds an optimization for Atmosphere packages by introducing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The ability to mark packages as &lt;code&gt;devOnly&lt;/code&gt;, so they’re fully removed from production builds.&lt;/li&gt;
&lt;li&gt;A new &lt;code&gt;Npm.devDepends&lt;/code&gt; option in your package.js to define dev dependencies, ensuring only the needed node modules for development are included during dev time and excluded from production (&lt;code&gt;meteor build&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After deploying the &lt;a href="https://galaxycloud.app/" rel="noopener noreferrer"&gt;Galaxy app&lt;/a&gt;, the total bundle size stored on the host machine &lt;strong&gt;dropped by about ~42%&lt;/strong&gt;. This improvement applies to all apps, since Meteor core packages now use the new Atmosphere optimization configuration. More gains will come as you update your own Atmosphere packages or community ones to properly skip dev-only packages and dependencies in production builds, leaving your final containers on hosts noticeably smaller.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.galaxycloud.app%2Fwp-content%2Fuploads%2F2026%2F01%2Fatmosphere-optimization.png" class="article-body-image-wrapper"&gt;&lt;img alt="image" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.galaxycloud.app%2Fwp-content%2Fuploads%2F2026%2F01%2Fatmosphere-optimization.png" width="632" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Modern Setups
&lt;/h3&gt;

&lt;p&gt;Meteor 3.4 introduces Rspack so you can &lt;strong&gt;configure modern setups&lt;/strong&gt; from the community.&lt;/p&gt;

&lt;p&gt;Supported setups include React, React Compiler, Vue, Solid, Svelte and Angular, all using their latest versions. Legacy setups like Coffeescript and Blaze remain supported, keeping older projects compatible.&lt;/p&gt;

&lt;p&gt;With this update, ESM packages are fully supported. Meteor apps can now use modules that rely on ESM behavior. A clear example is the support for React Router v7, a long-standing request from the community.&lt;/p&gt;

&lt;p&gt;Rspack also opens many new options. All Rspack or Webpack features can be configured in Meteor apps, including Workbox for Service Workers and PWA, asset imports and optimizations, and controlling the bundler lifecycle for custom behaviors and improvements.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Else Is New in Meteor 3.4?
&lt;/h2&gt;

&lt;p&gt;Thanks to the commitment of many of our community contributors, we have been able to expand this release with new features and optimizations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;react-meteor-data&lt;/code&gt; updated to &lt;code&gt;4.0.1&lt;/code&gt;, bringing improvements to suspense hooks and general optimizations. &lt;a href="https://github.com/welkinwong" rel="noopener noreferrer"&gt;@welkinwong&lt;/a&gt;, &lt;a href="https://github.com/malua" rel="noopener noreferrer"&gt;@malua&lt;/a&gt;, &lt;a href="https://github.com/evolross" rel="noopener noreferrer"&gt;@evolross&lt;/a&gt;, and &lt;a href="https://github.com/StorytellerCZ" rel="noopener noreferrer"&gt;@StorytellerCZ&lt;/a&gt; delivered these updates along with other maintenance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrated &lt;code&gt;collection-extensions&lt;/code&gt; into core, part of our goal to bring widely used packages across Meteor projects into core for better support and maintenance. Thanks to &lt;a href="https://github.com/harryadel" rel="noopener noreferrer"&gt;@harryadel&lt;/a&gt; for making this possible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cordova builds are now considered modern instead of legacy when &lt;code&gt;"modern": true&lt;/code&gt; is set in your project’s package.json. &lt;a href="https://github.com/tmeyer24" rel="noopener noreferrer"&gt;@tmeyer24&lt;/a&gt; prepared this change, laying the groundwork for future native updates with CapacitorJS or similar modern tools.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;--raw-logs&lt;/code&gt; is now the default in the Meteor CLI for development. &lt;a href="https://forums.meteor.com/u/paulishca" rel="noopener noreferrer"&gt;@paulishca&lt;/a&gt; suggested &lt;a href="https://forums.meteor.com/t/meteor-development-tiny-tip-that-helped-me-a-lot/64156" rel="noopener noreferrer"&gt;this&lt;/a&gt;, with &lt;a href="https://forums.meteor.com/t/meteor-development-tiny-tip-that-helped-me-a-lot/64156/4" rel="noopener noreferrer"&gt;full consensus&lt;/a&gt; from the community, and &lt;a href="https://github.com/Grubba27" rel="noopener noreferrer"&gt;@Grubba27&lt;/a&gt; provided the update quickly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More improvements and fixes were introduced in Meteor 3.4, &lt;a href="https://docs.meteor.com/history.html#v3-4-0-30-01-2026" rel="noopener noreferrer"&gt;see the changelog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more insights into the release, watch the release video:&lt;/p&gt;

&lt;p&gt;📹 &lt;a href="https://www.youtube.com/watch?v=qq_Fx2Y-Ec4" rel="noopener noreferrer"&gt;Meteor 3.4 and the road ahead - Galaxy Expansion Day 5&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more about the modern build stack, including Rspack, we joined Meteor Impact and gave a talk that explains its adoption, migration, and expected benefits.&lt;/p&gt;

&lt;p&gt;📹 &lt;a href="https://www.youtube.com/watch?v=LqU1eDbnG4I" rel="noopener noreferrer"&gt;Modern Build Stack in Meteor 3: Empower Your Meteor Apps with Faster, Feature-Rich Bundling&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Big Thanks to our contributors
&lt;/h2&gt;

&lt;p&gt;Reaching the 3.4 milestone would not have been possible without such an active and enthusiastic community. We want to highlight how important these contributions have been for this release.&lt;/p&gt;

&lt;p&gt;Thanks to our core contributors: &lt;a href="https://github.com/nachocodoner" rel="noopener noreferrer"&gt;@nachocodoner&lt;/a&gt;, &lt;a href="https://github.com/italojs" rel="noopener noreferrer"&gt;@italojs&lt;/a&gt;, &lt;a href="https://github.com/Grubba27" rel="noopener noreferrer"&gt;@Grubba27&lt;/a&gt;, &lt;a href="https://github.com/welkinwong" rel="noopener noreferrer"&gt;@welkinwong&lt;/a&gt;, &lt;a href="https://github.com/harryadel" rel="noopener noreferrer"&gt;@harryadel&lt;/a&gt;, &lt;a href="https://github.com/vparpoil" rel="noopener noreferrer"&gt;@vparpoil&lt;/a&gt;, &lt;a href="https://github.com/StorytellerCZ" rel="noopener noreferrer"&gt;@StorytellerCZ&lt;/a&gt;, &lt;a href="https://github.com/turoar23" rel="noopener noreferrer"&gt;@turoar23&lt;/a&gt;, &lt;a href="https://github.com/DipakHalkude" rel="noopener noreferrer"&gt;@DipakHalkude&lt;/a&gt;, &lt;a href="https://github.com/sanki92" rel="noopener noreferrer"&gt;@sanki92&lt;/a&gt;, &lt;a href="https://github.com/evolross" rel="noopener noreferrer"&gt;@evolross&lt;/a&gt;, &lt;a href="https://github.com/malua" rel="noopener noreferrer"&gt;@malua&lt;/a&gt;, &lt;a href="https://github.com/tmeyer24" rel="noopener noreferrer"&gt;@tmeyer24&lt;/a&gt;, &lt;a href="https://github.com/jeetburman" rel="noopener noreferrer"&gt;@jeetburman&lt;/a&gt; and &lt;a href="https://github.com/copleykj" rel="noopener noreferrer"&gt;@copleykj&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks to all community members for the testing and feedback on Meteor 3.4.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next for Meteor and Beyond?
&lt;/h2&gt;

&lt;p&gt;For the upcoming releases, we have the following priorities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stability and patches.&lt;/strong&gt; Collect feedback and fix issues. Planned &lt;em&gt;Meteor 3.4.x patches&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Change streams.&lt;/strong&gt; Unified MongoDB change notifications. Planned on &lt;em&gt;Meteor 3.5&lt;/em&gt; release./&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node 24.&lt;/strong&gt; Align with newer Node LTS releases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native.&lt;/strong&gt; Move toward a modern native solution beyond Cordova.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more details on upcoming work and priorities, see the &lt;a href="https://docs.meteor.com/about/roadmap.html" rel="noopener noreferrer"&gt;Meteor roadmap&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join the Meteor Renaissance!
&lt;/h2&gt;

&lt;p&gt;Meteor 3.4 wraps up the significant bundler changes we had envisioned. From these changes we will keep tweaking the bundler to expand and improve the experience if needed. Still, we’ll continue updating Meteor to revitalize the framework we all love in other areas as well.&lt;/p&gt;

&lt;p&gt;We’re excited about what’s to come and can’t wait for you to join the Meteor renaissance!&lt;/p&gt;

&lt;p&gt;For feedback, questions, or support, &lt;a href="https://forums.meteor.com/" rel="noopener noreferrer"&gt;visit our forums&lt;/a&gt; or &lt;a href="https://discord.com/invite/3w7EKdpghq" rel="noopener noreferrer"&gt;join our Discord channel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you find any issues, please report them to the &lt;a href="https://github.com/meteor/meteor/issues" rel="noopener noreferrer"&gt;Meteor issues tracker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Follow us on &lt;a href="https://x.com/meteorjs" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://github.com/meteor" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Stay tuned, and as always, happy coding! ☄️&lt;/p&gt;

</description>
      <category>meteor</category>
      <category>rspack</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>GitHub Actions + Galaxy: Zero-Downtime Deploy CI/CD</title>
      <dc:creator>Philippe Oliveira</dc:creator>
      <pubDate>Fri, 22 Aug 2025 14:55:43 +0000</pubDate>
      <link>https://forem.com/meteor/github-actions-galaxy-zero-downtime-deploy-cicd-complete-guide-42j0</link>
      <guid>https://forem.com/meteor/github-actions-galaxy-zero-downtime-deploy-cicd-complete-guide-42j0</guid>
      <description>&lt;p&gt;I recently set up a zero-downtime deploy pipeline for my Meteor app using GitHub Actions and Galaxy and honestly, it was way simpler than I expected.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through how I did it step by step. You’ll have a fully working push-to-deploy setup in minutes using secrets for safety, pinned Meteor versions for consistency, and Galaxy’s infrastructure for smooth deploys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Galaxy&lt;/strong&gt; is Meteor’s official cloud hosting platform designed for simple, reliable deployments with integrated monitoring.  &lt;/p&gt;

&lt;p&gt;Today, beyond Meteor, Galaxy also supports &lt;strong&gt;Node.js&lt;/strong&gt;, &lt;strong&gt;Python&lt;/strong&gt;, and databases like &lt;strong&gt;MongoDB&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://galaxycloud.app" rel="noopener noreferrer"&gt;Learn more here&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 What we’re building
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A GitHub Actions workflow that deploys your Meteor app to Galaxy automatically on every &lt;code&gt;main&lt;/code&gt; push&lt;/li&gt;
&lt;li&gt;Secure configuration using GitHub Secrets (no plain text credentials in the repo)&lt;/li&gt;
&lt;li&gt;Reliable, reproducible builds with a pinned Meteor release for consistency&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Why CI/CD with Actions helps
&lt;/h2&gt;

&lt;p&gt;If you’ve ever deployed Meteor locally, you know how resource-hungry the build process can be high CPU load, memory spikes, and your laptop fans going full throttle.&lt;/p&gt;

&lt;p&gt;Running this through &lt;strong&gt;GitHub Actions&lt;/strong&gt; takes that pain away:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Builds run entirely on GitHub’s hosted runners (Ubuntu VMs).&lt;/li&gt;
&lt;li&gt;Your machine stays free for real work no waiting around for Meteor to compile.&lt;/li&gt;
&lt;li&gt;Every run happens in a clean, isolated environment, so you avoid “works on my machine” problems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result: faster, more consistent deploys, no local slowdowns, and zero babysitting during the build.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Useful links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://help.galaxycloud.app/en/article/deploy-a-new-meteor-app-using-the-cli-1vzo6do/" rel="noopener noreferrer"&gt;Galaxy CLI deploy docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://help.galaxycloud.app/en/article/regions-meteor-apps-1vucejm/" rel="noopener noreferrer"&gt;Galaxy regions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GitHub Action: &lt;a href="https://github.com/aquinoit/simpletasks-ghactions" rel="noopener noreferrer"&gt;&lt;code&gt;aquinoit/simpletasks-ghactions&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ Prerequisites
&lt;/h2&gt;

&lt;p&gt;You’ll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A live Galaxy app (e.g. &lt;code&gt;myapp.meteorapp.com&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;MongoDB configured via your app settings&lt;/li&gt;
&lt;li&gt;A GitHub repo with Actions enabled&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1️⃣ Create a Meteor session (local, one-time)
&lt;/h2&gt;

&lt;p&gt;Meteor’s CLI deploy requires a valid session. We’ll create one locally and convert it to base64 to use securely in GitHub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;METEOR_SESSION_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;./meteor_session.json meteor login
&lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;-w0&lt;/span&gt; meteor_session.json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; meteor_session.b64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the base64 string output — we’ll add this as a GitHub Secret.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3y20lapygdhsuctxofw2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3y20lapygdhsuctxofw2.png" alt="1" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2️⃣ Add your GitHub Secrets
&lt;/h2&gt;

&lt;p&gt;Go to your repo → &lt;strong&gt;Settings → Secrets and variables → Actions → New repository secret&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add the following two secrets:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Secret Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;METEOR_SESSION_B64&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Paste the contents of &lt;code&gt;meteor_session.b64&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;METEOR_SETTINGS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your app’s settings JSON (as a single line)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Tip: use &lt;code&gt;jq -c&lt;/code&gt; to compress your settings file into one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jq &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; settings.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhry6ot1kgjuv3uxjlhf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhry6ot1kgjuv3uxjlhf.png" alt="2" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;










&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcioqvhd2h52ghq2wuo4s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcioqvhd2h52ghq2wuo4s.png" alt="2" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;










&lt;h2&gt;
  
  
  3️⃣ Add the deploy workflow
&lt;/h2&gt;

&lt;p&gt;In your project, create a file at &lt;code&gt;.github/workflows/deploy.yml&lt;/code&gt; with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build &amp;amp; Deploy to Galaxy&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;meteorengineer/setup-meteor@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;meteor-release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2.14'&lt;/span&gt;  &lt;span class="c1"&gt;# Use your exact Meteor version&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;meteor npm install&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Write settings.json&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;printf '%s' '${{ secrets.METEOR_SETTINGS }}' &amp;gt; settings.json&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Show Settings&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cat settings.json&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Galaxy&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aquinoit/galaxy-ghactions@0.0.2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;meteor_session_base64&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.METEOR_SESSION_B64 }}&lt;/span&gt;
          &lt;span class="na"&gt;app_hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp.meteorapp.com&lt;/span&gt;
          &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;galaxy.meteor.com&lt;/span&gt;
          &lt;span class="na"&gt;settings_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./settings.json&lt;/span&gt;
          &lt;span class="na"&gt;deploy_flags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--free'&lt;/span&gt;
          &lt;span class="na"&gt;npm_install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;true'&lt;/span&gt;
          &lt;span class="na"&gt;npm_install_args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;












&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezsu3pqk3vn3wfy2yi7o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezsu3pqk3vn3wfy2yi7o.png" alt="2" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  4️⃣ Push and deploy
&lt;/h2&gt;

&lt;p&gt;Now commit and push to &lt;code&gt;main&lt;/code&gt;. The workflow will run automatically and deploy your app to Galaxy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"ci: automatic deploy to Galaxy"&lt;/span&gt;
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then on GitHub:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the &lt;strong&gt;Actions&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Build &amp;amp; Deploy to Galaxy&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Watch the logs in real time!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4zno0563l0cxtlwov0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4zno0563l0cxtlwov0w.png" alt="3" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;










&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fin00wmsln1qq4qdv1d10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fin00wmsln1qq4qdv1d10.png" alt="4" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔐 Secrets &amp;amp; best practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never&lt;/strong&gt; commit &lt;code&gt;settings.json&lt;/code&gt;. The workflow writes it at runtime.&lt;/li&gt;
&lt;li&gt;Use a Meteor account with the minimum necessary access for deployment.&lt;/li&gt;
&lt;li&gt;Consider separate workflows for production and staging environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafrwdfyakera2pvpbw8p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafrwdfyakera2pvpbw8p.png" alt="5" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧯 Common issues &amp;amp; fixes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Meteor “superuser” warning&lt;/strong&gt;&lt;br&gt;
You can ignore this. The action already includes &lt;code&gt;--allow-superuser&lt;/code&gt; internally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploying to the wrong region?&lt;/strong&gt;&lt;br&gt;
Use the correct region hostname:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;US: &lt;code&gt;galaxy.meteor.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;EU: &lt;code&gt;eu-west-1.galaxy.meteor.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;APAC: &lt;code&gt;ap-southeast-2.galaxy.meteor.com&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;“Can’t find action” error?&lt;/strong&gt;&lt;br&gt;
Make sure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have &lt;code&gt;uses: aquinoit/galaxy-ghactions@0.0.2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You’ve included the &lt;code&gt;checkout&lt;/code&gt; step at the top&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Production tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Pin your Meteor version in the workflow to avoid surprises&lt;/li&gt;
&lt;li&gt;Add a second workflow for &lt;code&gt;develop&lt;/code&gt; → staging app&lt;/li&gt;
&lt;li&gt;You can also enable manual deployments with workflow_dispatch in your workflow. This allows you to trigger a deploy from the GitHub Actions UI, without pushing a commit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fereqwx9q7ml6j2ve8anh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fereqwx9q7ml6j2ve8anh.png" alt="6" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Final thoughts
&lt;/h2&gt;

&lt;p&gt;That’s it! You now have a clean, secure CI/CD pipeline that deploys your Meteor app to Galaxy automatically — with &lt;strong&gt;zero downtime&lt;/strong&gt;. Just push to &lt;code&gt;main&lt;/code&gt; and watch it go live in seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fycgkmhpfcfqdbawnkcnv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fycgkmhpfcfqdbawnkcnv.png" alt="7" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;










&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pjet96ehmpc5uhy5j9i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pjet96ehmpc5uhy5j9i.png" alt="8" width="800" height="209"&gt;&lt;/a&gt;&lt;/p&gt;













&lt;h2&gt;
  
  
  🔗 More resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://help.galaxycloud.app/en/article/deploy-a-new-meteor-app-using-the-cli-1vzo6do/" rel="noopener noreferrer"&gt;Galaxy CLI deploy guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://help.galaxycloud.app/en/article/regions-meteor-apps-1vucejm/" rel="noopener noreferrer"&gt;Galaxy Regions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔮 Coming soon: GitLab CI and Bitbucket Pipelines
&lt;/h2&gt;

&lt;p&gt;This guide focused on GitHub Actions, but I’ll soon publish versions tailored for GitLab CI and Bitbucket Pipelines.&lt;/p&gt;

&lt;p&gt;So if your team uses those platforms, stay tuned the same zero-downtime deployment approach applies, just with different syntax.&lt;/p&gt;

&lt;p&gt;Let me know if this was helpful or if you hit any issues while setting it up happy to help!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Faster Builds in Meteor 3.3: Modern Build Stack with SWC and Bundler Optimizations</title>
      <dc:creator>Nacho Codoñer</dc:creator>
      <pubDate>Tue, 17 Jun 2025 14:41:26 +0000</pubDate>
      <link>https://forem.com/meteor/faster-builds-in-meteor-33-modern-build-stack-with-swc-and-bundler-optimizations-fm2</link>
      <guid>https://forem.com/meteor/faster-builds-in-meteor-33-modern-build-stack-with-swc-and-bundler-optimizations-fm2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Meteor 3.3 slashes build times&lt;/strong&gt; by around &lt;strong&gt;60% on average&lt;/strong&gt;, with some projects building over &lt;strong&gt;3× faster builds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is the first major update to the Meteor bundler in years, introducing several optimizations. The main change is switching from Babel to SWC for transpiling and minifying to speed up builds. We reviewed and optimized the bundler’s components to improve the development experience.&lt;/p&gt;

&lt;p&gt;On our core team, we’ve already seen these gains after upgrading the &lt;a href="https://galaxycloud.app" rel="noopener noreferrer"&gt;Galaxy Cloud app&lt;/a&gt;, and the cloud team’s development and delivery have become significantly faster. This post details the changes and shows the Galaxy app’s improvement metrics as an example of what to expect with your Meteor 3.3 upgrade.&lt;/p&gt;

&lt;p&gt;This release also includes community contributions for Meteor React packages, improving stability and performance of common hooks and adding support for React 19.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started: A Quick Hands-On
&lt;/h2&gt;

&lt;p&gt;To start using Meteor 3.3.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update Your App
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Update your existing Meteor app to version 3.3&lt;/span&gt;
meteor update &lt;span class="nt"&gt;--release&lt;/span&gt; 3.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a New App
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a new Meteor app using Meteor 3.3&lt;/span&gt;
meteor create my-app &lt;span class="nt"&gt;--release&lt;/span&gt; 3.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add this to your &lt;code&gt;package.json&lt;/code&gt; to enable the new modern build stack:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"meteor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"modern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This setting is on by default for new apps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Highlights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Modern Build Stack
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Meteor 3.3&lt;/strong&gt; brings a new build stack: SWC for transpiling and minifying, &lt;code&gt;@parcel/watcher&lt;/code&gt; for file watching, and smarter skips for legacy bundles.&lt;/p&gt;

&lt;p&gt;Turn on &lt;code&gt;"modern": true&lt;/code&gt; in your &lt;code&gt;package.json&lt;/code&gt; and see rebuilds and builds fly!&lt;/p&gt;

&lt;p&gt;On average, &lt;strong&gt;build and rebuild times are cut by about 60%&lt;/strong&gt;, roughly a &lt;strong&gt;3× speed-up&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These results come from &lt;a href="https://galaxycloud.app" rel="noopener noreferrer"&gt;the Galaxy Cloud app&lt;/a&gt;. In the next sections, we break down improvements for development and production experiences. Your app’s numbers may differ, but you can expect similar gains.&lt;/p&gt;

&lt;p&gt;Curious about the gains? Run &lt;code&gt;meteor profile&lt;/code&gt; to compare Meteor 3.2 vs 3.3 on your project and share your results!&lt;/p&gt;

&lt;h4&gt;
  
  
  Development Breakdown
&lt;/h4&gt;

&lt;p&gt;When running &lt;code&gt;meteor run&lt;/code&gt;, timings from &lt;code&gt;meteor profile&lt;/code&gt; in Meteor 3.2 vs 3.3.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4o1z3huaxbm9w7rhis4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu4o1z3huaxbm9w7rhis4.png" alt=" raw `meteor profile` endraw  in Meteor 3.2 vs 3.3" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzehghwbuv2x1u67pwb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzehghwbuv2x1u67pwb1.png" alt="Summary  raw `meteor profile` endraw  in Meteor 3.2 vs 3.3" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On average, these runs show about a &lt;strong&gt;60% reduction in build times&lt;/strong&gt;, corresponding to roughly a 2.7× speed-up, and &lt;strong&gt;exceeding 3×&lt;/strong&gt; in many cases. &lt;/p&gt;

&lt;h4&gt;
  
  
  Production Breakdown
&lt;/h4&gt;

&lt;p&gt;When running &lt;code&gt;meteor build&lt;/code&gt;, timings from &lt;code&gt;meteor profile --build&lt;/code&gt; with and without &lt;code&gt;"modern": true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwts6rqw7yt6w0lg3dr5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwts6rqw7yt6w0lg3dr5.png" alt=" raw `meteor profile - build` endraw  in Meteor modern vs legacy" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F18l6r902nbu3x9k02fxi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F18l6r902nbu3x9k02fxi.png" alt="Summary  raw `meteor profile - build` endraw  in Meteor modern vs legacy" width="800" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On average, these runs show about a &lt;strong&gt;60% reduction&lt;/strong&gt;, corresponding to roughly a 2.5× speed-up.&lt;/p&gt;

&lt;h4&gt;
  
  
  Build Stack Upgrade
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Transpiler
&lt;/h5&gt;

&lt;blockquote&gt;
&lt;p&gt;The transpiler converts modern JS syntax in all app code to a cross-browser compatible version.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Meteor profiling showed most build time goes to Babel transpilation (&lt;code&gt;meteor run&lt;/code&gt;/&lt;code&gt;meteor build&lt;/code&gt;). To fix this, we added SWC (in Rust), which speeds up rebuilds in both development and production.&lt;/p&gt;

&lt;p&gt;There are no breaking changes for most apps. If your app uses &lt;a href="https://docs.meteor.com/about/modern-build-stack/transpiler-swc.html#nested-imports" rel="noopener noreferrer"&gt;nested imports&lt;/a&gt; (not dynamic ones), it may fall back to Babel. The same applies if you use Babel plugins that SWC does not support yet. You can find SWC equivalents or disable SWC for those files.&lt;/p&gt;

&lt;p&gt;We also added a doc page with tips for migrating and debugging the new setup.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://docs.meteor.com/about/modern-build-stack/transpiler-swc.html#transpiler-swc" rel="noopener noreferrer"&gt;&lt;strong&gt;Modern Transpiler: SWC docs&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Minifier
&lt;/h5&gt;

&lt;blockquote&gt;
&lt;p&gt;The minifier reduces and obfuscates your app’s production bundle for security and efficiency.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Meteor profiling showed Terser spends a lot of time on production builds (&lt;code&gt;meteor build&lt;/code&gt;). To fix this, we added the SWC minifier, which speeds up builds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/italojs" rel="noopener noreferrer"&gt;@italojs&lt;/a&gt; adapted the minifier from the &lt;a href="https://github.com/zodern" rel="noopener noreferrer"&gt;zodern&lt;/a&gt;/&lt;a href="https://github.com/zodern/minify-js-sourcemaps" rel="noopener noreferrer"&gt;minify-js-sourcemaps&lt;/a&gt; package, cherry-picked it, and integrated it into Meteor core, delivering the performance gains we wanted.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://docs.meteor.com/about/modern-build-stack/bundler.html#minifier" rel="noopener noreferrer"&gt;&lt;strong&gt;Modern Bundler: Minifier docs&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Web archs
&lt;/h5&gt;

&lt;blockquote&gt;
&lt;p&gt;Web archs are the builds Meteor generates for modern browsers, legacy browsers, and Cordova.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Skipping &lt;code&gt;web.browser.legacy&lt;/code&gt; and &lt;code&gt;web.cordova&lt;/code&gt; speeds up builds. In development mode, Meteor skips these archs when they aren’t needed.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://github.com/9Morello" rel="noopener noreferrer"&gt;@9Morello&lt;/a&gt; for driving this forward!&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://docs.meteor.com/about/modern-build-stack/bundler.html#web-arch" rel="noopener noreferrer"&gt;&lt;strong&gt;Modern Bundler: Web Arch docs&lt;/strong&gt; &lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Watcher
&lt;/h5&gt;

&lt;blockquote&gt;
&lt;p&gt;The watcher listens for changes in your app’s code files and triggers quick recompilations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Meteor now uses &lt;a href="https://github.com/parcel-bundler/watcher" rel="noopener noreferrer"&gt;&lt;code&gt;@parcel/watcher&lt;/code&gt;&lt;/a&gt;. This improves development mode speed and compatibility by using native, recursive file watching on all OS. It also fixes a long-standing Linux delay where file changes took 5 seconds to register.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://docs.meteor.com/about/modern-build-stack/dev-server.html#watcher" rel="noopener noreferrer"&gt;&lt;strong&gt;Modern Dev Server: Watcher docs&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools: CPU profiling
&lt;/h3&gt;

&lt;p&gt;Observability is crucial for data-driven releases. In our effort to enable this, we’ve improved our profiling tools and made them available to everyone.&lt;/p&gt;

&lt;p&gt;We added environment variables to generate and inspect CPU profiles. In his guide, &lt;a href="https://github.com/italojs" rel="noopener noreferrer"&gt;@italojs&lt;/a&gt; shows &lt;a href="https://dev.to/meteor/enhancing-performance-in-meteorjs-bundler-complete-guide-to-cpu-profiling-4igo"&gt;how to run these profiles and pinpoints Babel as a bottleneck&lt;/a&gt; now replaced by SWC in 3.3.&lt;/p&gt;

&lt;p&gt;We enhanced &lt;a href="https://dev.to/meteor/unlocking-meteor-32-new-profiling-tool-to-track-bundler-performance-and-size-1jc8"&gt;the &lt;code&gt;meteor profile&lt;/code&gt; command introduced in Meteor 3.2&lt;/a&gt;. It now includes a &lt;code&gt;--build&lt;/code&gt; flag to profile the production build and highlight minifier gains. Rebuild reports now emphasize total rebuild times so you can track client and server build improvements.&lt;/p&gt;

&lt;h3&gt;
  
  
  React 19 Support
&lt;/h3&gt;

&lt;p&gt;We updated the &lt;a href="https://github.com/meteor/react-packages" rel="noopener noreferrer"&gt;&lt;code&gt;meteor/react-packages&lt;/code&gt; repo&lt;/a&gt; to restore tests/CI and ensure compatibility with Meteor 3. Contributors also improved the performance of &lt;code&gt;useFind&lt;/code&gt; and &lt;code&gt;useSubscribe&lt;/code&gt;, and added React 19 support.&lt;/p&gt;

&lt;p&gt;Try the new beta of &lt;a href="https://docs.meteor.com/packages/react-meteor-data" rel="noopener noreferrer"&gt;&lt;code&gt;react-meteor-data&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;meteor add react-meteor-data@4.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks to &lt;a href="https://github.com/welkinwong" rel="noopener noreferrer"&gt;@welkinwong&lt;/a&gt;, &lt;a href="https://github.com/Poyoman39" rel="noopener noreferrer"&gt;@Poyoman39&lt;/a&gt;, and &lt;a href="https://github.com/PedroMarianoAlmeida" rel="noopener noreferrer"&gt;@PedroMarianoAlmeida&lt;/a&gt; for their contributions and tests!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Be aware of a breaking change: useFind describes no deps by default &lt;a href="https://github.com/meteor/react-packages/pull/431" rel="noopener noreferrer"&gt;#431&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Else Is New in Meteor 3.3?
&lt;/h2&gt;

&lt;p&gt;For full details on what’s included in Meteor 3.3, &lt;a href="https://v3-docs.meteor.com/history.html#v3-3-0-2025-06-11" rel="noopener noreferrer"&gt;see the changelog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more insights into the release, &lt;a href="https://www.youtube.com/watch?v=cPIFrU-IBkM" rel="noopener noreferrer"&gt;watch the release video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We want to highlight how important community members contributions have been in delivering these changes.&lt;/p&gt;

&lt;p&gt;Thanks to our core contributors: &lt;a href="https://github.com/nachocodoner" rel="noopener noreferrer"&gt;@nachocodoner&lt;/a&gt;, &lt;a href="https://github.com/italojs" rel="noopener noreferrer"&gt;@italojs&lt;/a&gt;, &lt;a href="https://github.com/Grubba27" rel="noopener noreferrer"&gt;@Grubba27&lt;/a&gt;, &lt;a href="https://github.com/zodern" rel="noopener noreferrer"&gt;@zodern&lt;/a&gt;, &lt;a href="https://github.com/9Morello" rel="noopener noreferrer"&gt;@9Morello&lt;/a&gt;, &lt;a href="https://github.com/welkinwong" rel="noopener noreferrer"&gt;@welkinwong&lt;/a&gt;, &lt;a href="https://github.com/Poyoman39" rel="noopener noreferrer"&gt;@Poyoman39&lt;/a&gt;, &lt;a href="https://github.com/PedroMarianoAlmeida" rel="noopener noreferrer"&gt;@PedroMarianoAlmeida&lt;/a&gt;, &lt;a href="https://github.com/harryadel" rel="noopener noreferrer"&gt;@harryadel&lt;/a&gt;, &lt;a href="https://github.com/ericm546" rel="noopener noreferrer"&gt;@ericm546&lt;/a&gt;, &lt;a href="https://github.com/StorytellerCZ" rel="noopener noreferrer"&gt;@StorytellerCZ&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to community members for testing and feedback on Meteor 3.3: &lt;a href="https://github.com/zodern" rel="noopener noreferrer"&gt;@zodern&lt;/a&gt;, &lt;a href="https://forums.meteor.com/u/minhna" rel="noopener noreferrer"&gt;@minhna&lt;/a&gt;, &lt;a href="https://forums.meteor.com/u/paulishca" rel="noopener noreferrer"&gt;@paulishca&lt;/a&gt;, &lt;a href="https://forums.meteor.com/u/pmogollon" rel="noopener noreferrer"&gt;@pmogollon&lt;/a&gt;, &lt;a href="https://forums.meteor.com/u/ferjep" rel="noopener noreferrer"&gt;@ferjep&lt;/a&gt;, &lt;a href="https://forums.meteor.com/u/wreiske" rel="noopener noreferrer"&gt;@wreiske&lt;/a&gt;, &lt;a href="https://forums.meteor.com/u/schlaegerz" rel="noopener noreferrer"&gt;@schlaegerz&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next for Meteor and Beyond?
&lt;/h2&gt;

&lt;p&gt;For the upcoming releases, we have the following priorities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stability and patches.&lt;/strong&gt; Collect feedback, fix missing support or issues in modern build stack, and ship pending contributions. Planned &lt;em&gt;Meteor 3.3.x patches&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modern bundler.&lt;/strong&gt; Integrate a bundler that meets current standards for performance, tooling, plugin support, and community growth. Planned for &lt;em&gt;Meteor 3.4&lt;/em&gt;. A demonstration is available, please share your feedback on the &lt;a href="https://forums.meteor.com/t/meteor-rspack-integration-a-modern-bundler-meets-meteor-3-4/63696" rel="noopener noreferrer"&gt;Meteor-RSPack integration&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Change streams.&lt;/strong&gt; Provide a unified API for MongoDB change notifications to improve efficiency and consistency. Research is underway, please share your feedback: &lt;a href="https://forums.meteor.com/t/mongodb-change-streams-support-in-meteor-feedback-wanted/63681" rel="noopener noreferrer"&gt;MongoDB Change Streams support in Meteor&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To learn more about upcoming work, &lt;a href="https://docs.meteor.com/about/roadmap" rel="noopener noreferrer"&gt;see the Meteor roadmap&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Join the Meteor Renaissance!
&lt;/h2&gt;

&lt;p&gt;Meteor 3.3 delivers significantly faster build times for your Meteor app development experience. These changes are just the beginning; we’ll continue updating Meteor to revitalize the framework we all love.&lt;/p&gt;

&lt;p&gt;We’re excited about what’s to come and can’t wait for you to join the Meteor renaissance!&lt;/p&gt;

&lt;p&gt;For feedback, questions, or support, &lt;a href="https://forums.meteor.com/" rel="noopener noreferrer"&gt;visit our forums&lt;/a&gt; or &lt;a href="https://discord.com/invite/3w7EKdpghq" rel="noopener noreferrer"&gt;join our Discord channel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you find any issues, please report them to the &lt;a href="https://github.com/meteor/meteor/issues" rel="noopener noreferrer"&gt;Meteor issues tracker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Follow us on &lt;a href="https://x.com/meteorjs" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://github.com/meteor" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Stay tuned, and as always, happy coding! ☄️&lt;/p&gt;

</description>
      <category>meteor</category>
      <category>javascript</category>
      <category>performance</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Big Changes at Meteor Software: Our Next Chapter</title>
      <dc:creator>Frederico Maia</dc:creator>
      <pubDate>Fri, 16 May 2025 17:02:54 +0000</pubDate>
      <link>https://forem.com/meteor/big-changes-at-meteor-software-our-next-chapter-g22</link>
      <guid>https://forem.com/meteor/big-changes-at-meteor-software-our-next-chapter-g22</guid>
      <description>&lt;p&gt;As the CEO of Meteor Software for the past 3 years, I wanted to share some major exciting things about where we're heading. When I first joined the company, I had a clear vision to modernize &lt;a href="https://meteor.com" rel="noopener noreferrer"&gt;Meteor&lt;/a&gt; and transform &lt;a href="https://galaxycloud.app" rel="noopener noreferrer"&gt;Galaxy&lt;/a&gt; into something bigger.&lt;/p&gt;

&lt;p&gt;Today, I'm excited to tell you that these changes are finally happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  A New Era, A New Identity
&lt;/h2&gt;

&lt;p&gt;First things first! We're introducing fresh new brands for both Meteor and Galaxy. This isn't just a cosmetic facelift. It shows that we are changing our direction in a significant way.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1vpkqadr6p0lqylh2zjc.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1vpkqadr6p0lqylh2zjc.webp" alt="Screenshot of the previous Meteor website" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fracmohm33tzswdgq4h89.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fracmohm33tzswdgq4h89.png" alt="Screenshot of the new Meteor website" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We've been using the original Meteor logo for more than 13 years, and it has become quite recognizable within the JavaScript community. The decision to change it wasn't made hastily, but we felt it was essential to reflect our ongoing evolution.&lt;/p&gt;

&lt;p&gt;Our new Meteor brand represents our commitment to modern JavaScript. It features a cleaner, more contemporary design that represents our future direction rather than just our heritage. The redesigned &lt;a href="https://meteor.com" rel="noopener noreferrer"&gt;Meteor website&lt;/a&gt; is now ready and includes a really cool interactive demo that showcases what Meteor can do. We're excited for you to check it out and experience Meteor's capabilities firsthand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgp2g0jjynfchhv47wpu1.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgp2g0jjynfchhv47wpu1.webp" alt="Screenshot of the previous Galaxy website" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhpk2h8bdonsmz7sdpet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhpk2h8bdonsmz7sdpet.png" alt="Screenshot of the new Galaxy website" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Meanwhile, Galaxy's new independent brand shows it's growing beyond its Meteor-only roots into a robust, multi-stack cloud platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meteor 3: Embracing the Node.js Ecosystem
&lt;/h2&gt;

&lt;p&gt;After countless long nights and coffee-fueled coding sessions, we released Meteor 3.0 in July 2024 (now we're at version 3.2). This release wasn't just another version bump. It shows where we want to go in the future. We changed from using Fibers to using async/await, which is what most developers use now. We also support the newest version of Node.js. These changes help Meteor work better with other Node.js tools.&lt;/p&gt;

&lt;p&gt;This is important because instead of maintaining our own solutions for everything, we're now able to use the best tools the JavaScript ecosystem has to offer. Why reinvent the wheel when there are already amazing solutions out there? Since I started working at Meteor Software, I wanted Meteor to work well with other Node.js tools instead of being separate and alone.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's Coming in 2025
&lt;/h3&gt;

&lt;p&gt;Looking ahead, our &lt;a href="https://docs.meteor.com/about/roadmap.html" rel="noopener noreferrer"&gt;2025 roadmap&lt;/a&gt; shows exactly where we're heading. We're embracing integration with powerful, proven tools instead of making everything ourselves.&lt;/p&gt;

&lt;h4&gt;
  
  
  Bundle Optimization: Our Current Priority
&lt;/h4&gt;

&lt;p&gt;We're working to make Meteor apps smaller and faster:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Working with modern bundlers:&lt;/strong&gt; We're making it easy to use RSPack, ESBuild, and Rollup so your apps will load faster and use less memory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster builds:&lt;/strong&gt; With our new tools (added in version 3.2), we're making builds take less time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better development experience:&lt;/strong&gt; Making changes to your code will show up more quickly while you're developing&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Other Important Improvements
&lt;/h4&gt;

&lt;p&gt;We are also going to work on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modernized RPC Methods and Publications:&lt;/strong&gt; Adding self-documenting code, better validation, and more intuitive interfaces while maintaining backward compatibility&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MongoDB Change Streams:&lt;/strong&gt; Using the official way to get real-time updates from MongoDB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better TypeScript support:&lt;/strong&gt; Making it easier to use TypeScript with Meteor and its packages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CapacitorJS for mobile apps:&lt;/strong&gt; A better, newer way to build mobile apps than our old Cordova system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster releases:&lt;/strong&gt; Making our own process quicker so you get updates sooner&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these changes will solve real problems that developers face every day.&lt;/p&gt;

&lt;p&gt;We will write clear, helpful guides about all these new features so everyone can use them easily, whether you're new to Meteor or have used it for years.&lt;/p&gt;

&lt;h2&gt;
  
  
  Galaxy Expands Its Universe
&lt;/h2&gt;

&lt;p&gt;I'm particularly excited to share what is perhaps our most significant announcement. Galaxy is undergoing a comprehensive transformation. Upon joining the company, I recognized Galaxy's potential to evolve beyond its role as a Meteor-only hosting platform. Today, I'm pleased to announce that we're realizing this ambitious vision.&lt;/p&gt;

&lt;p&gt;Galaxy 2.0 integrates our previous dashboard and backend systems into a cohesive, intuitive platform that significantly enhances the user experience. The truly revolutionary aspect, however, is Galaxy's expanded support capabilities. &lt;strong&gt;The platform now supports Node.js and Python applications, including frameworks such as Express, Nest, Adonis, Flask, and Django.&lt;/strong&gt; And we're developing support for Ruby on Rails, which will be available in the coming months.&lt;/p&gt;

&lt;p&gt;Our promise is simple but powerful. We'll provide the most user-friendly cloud platform and the most responsive support team available. We believe cloud hosting shouldn't be complicated, and when you need help, you deserve proper answers from people who understand your challenges.&lt;/p&gt;

&lt;h3&gt;
  
  
  Complete Platform with Database Solutions
&lt;/h3&gt;

&lt;p&gt;In 2024, we enhanced Galaxy by adding MongoDB hosting directly on the platform. This significantly simplified deployments for teams needing reliable, managed MongoDB solutions. We're continuing this evolution in 2025 by expanding our database offerings to include PostgreSQL, Redis, and FerretDB.&lt;/p&gt;

&lt;p&gt;These additions transform Galaxy into a comprehensive platform for hosting applications and databases together, streamlining deployment and management considerably.&lt;/p&gt;

&lt;p&gt;This isn't just an upgrade. It's a complete transformation. Galaxy now operates as an independent platform with its own &lt;a href="https://galaxycloud.app" rel="noopener noreferrer"&gt;dedicated website&lt;/a&gt; and distinct brand identity separate from Meteor. The new Galaxy brand reflects our commitment to serving a wider developer community while maintaining the reliability our users expect. We're making a substantial investment in this expansion for 2025.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Team Structure
&lt;/h2&gt;

&lt;p&gt;I want to be transparent about our organization. These advancements are being delivered by dedicated, autonomous teams working diligently behind the scenes.&lt;/p&gt;

&lt;p&gt;We operate with two specialized technical teams, each led by its own tech lead while sharing the same CTO. The teams maintain separate roadmaps and priorities, focusing exclusively on their respective products. The Galaxy team advances our cloud platform, while the Meteor team enhances and maintains our open-source framework. Our DevOps specialists, though formally part of the Galaxy team, provide support to both divisions when infrastructure requirements arise.&lt;/p&gt;

&lt;p&gt;This organizational approach ensures consistent attention to both products, with Meteor and Galaxy each receiving the focused development they require.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why These Changes Matter
&lt;/h2&gt;

&lt;p&gt;I won't present you with buzzwords or empty promises. As developers ourselves, we understand what's truly important: reliable tools that enhance productivity and effectiveness. These changes address genuine requirements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Meteor requires improvements on DX, scaling, and compatibility with modern JavaScript&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Galaxy needed to support additional technologies because that's what teams actually use in the real world&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Both products needed to communicate their evolution with new, modern brand identities&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The refreshed branding for Meteor and Galaxy isn't merely cosmetic. These are deliberate declarations of our direction. They demonstrate our dedication to innovation and our readiness to meet current development demands. The real improvements are in the technology and its capabilities. We're committed to developing robust, practical solutions for real-world development challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Today
&lt;/h2&gt;

&lt;p&gt;If you're a Meteor developer, I encourage you to upgrade to Meteor 3 today. You'll immediately feel the benefits of native async/await and modern Node.js features. Meteor 3.3, which &lt;a href="https://forums.meteor.com/t/weekly-update-may-16-2025-new-3-3-beta-1-release-faster-builds-delivered/63612" rel="noopener noreferrer"&gt;is currently in beta&lt;/a&gt;, already brings faster builds. Check out &lt;a href="https://docs.meteor.com" rel="noopener noreferrer"&gt;Meteor 3 docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For those working with Node.js, Python, and their popular frameworks, consider exploring Galaxy. Visit our &lt;a href="https://galaxycloud.app" rel="noopener noreferrer"&gt;new Galaxy website&lt;/a&gt; to discover how we've simplified cloud deployment.&lt;/p&gt;

&lt;p&gt;I'm really proud of what our teams have built, but we're just getting started. There's so much more coming down the pipeline, and we'll keep you updated as we roll out new features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's build amazing things together.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>meteor</category>
      <category>python</category>
    </item>
    <item>
      <title>Enhancing Performance in MeteorJS bundler: Complete Guide to CPU Profiling</title>
      <dc:creator>italojs</dc:creator>
      <pubDate>Fri, 28 Mar 2025 19:20:50 +0000</pubDate>
      <link>https://forem.com/meteor/enhancing-performance-in-meteorjs-bundler-complete-guide-to-cpu-profiling-4igo</link>
      <guid>https://forem.com/meteor/enhancing-performance-in-meteorjs-bundler-complete-guide-to-cpu-profiling-4igo</guid>
      <description>&lt;p&gt;Performance is a fundamental concern for any modern web application, and Meteor apps are no exception. Currently, one of our main focuses is optimizing the Meteor bundler, which can be a significant bottleneck in larger projects. Although Meteor already offers built-in tools for performance analysis, using native CPU profiling can provide much deeper insights into performance bottlenecks. In this article, we'll explore how to effectively use CPU profiling in Meteor, including the difference between Meteor's current profiling system and native profiling based on Node.js Inspector, with special emphasis on how this can help improve the bundling process.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is CPU Profiling?
&lt;/h2&gt;

&lt;p&gt;CPU profiling is a performance analysis technique that tracks exactly which functions are being executed by the CPU, for how long, and how frequently. This type of analysis allows you to identify precisely where your code is spending the most processing time.&lt;/p&gt;

&lt;p&gt;Unlike simple time measurement techniques (like basic timers), CPU profiling creates a comprehensive view of code execution, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Function call tree - shows which functions call other functions&lt;/li&gt;
&lt;li&gt;Execution time for each function&lt;/li&gt;
&lt;li&gt;Frequency of calls for each function&lt;/li&gt;
&lt;li&gt;Memory allocation (in some cases)&lt;/li&gt;
&lt;li&gt;Call stack visualization&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Current Meteor Profiling vs Native CPU Profiling
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Meteor's Built-in Profiling System
&lt;/h3&gt;

&lt;p&gt;Meteor has a built-in profiling system that can be activated by setting the &lt;code&gt;METEOR_PROFILE&lt;/code&gt; environment variable. This system uses a timer-based measurement approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;METEOR_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 meteor &amp;lt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This profiler is designed specifically for the Meteor ecosystem and works through manual code instrumentation. The result is a report that shows the time spent on different Meteor operations, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| (#1) Profiling: ProjectContext prepareProjectForBuild
| ProjectContext prepareProjectForBuild..........9,207 ms (1)
|    _initializeCatalog.............................24 ms (1)
|       files.readFile                               7 ms (2)
|       runJavaScript package.js                     2 ms (1)
|       files.rm_recursive                           4 ms (4)
|       other _initializeCatalog                    11 ms
|    _resolveConstraints.........................6,702 ms (1)
|       bundler.readJsImage.........................42 ms (1)
...
| (#1) Total: 9,544 ms (ProjectContext prepareProjectForBuild)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Native CPU Profiling with Node.js Inspector
&lt;/h3&gt;

&lt;p&gt;Recent versions of Meteor have included support for native CPU profiling using Node.js's &lt;code&gt;inspector&lt;/code&gt; module. This approach generates &lt;code&gt;.cpuprofile&lt;/code&gt; files that provide much more detailed data and can be analyzed with advanced tools such as Chrome DevTools or cpupro.&lt;/p&gt;

&lt;p&gt;To enable native CPU profiling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;METEOR_INSPECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bundler.bundle,compiler.compile meteor &amp;lt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Advantages of Native CPU Profiling:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Complete execution view:&lt;/strong&gt; Captures all functions being executed, not just those manually instrumented&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive analysis:&lt;/strong&gt; Allows you to visually explore and filter performance data using graphical tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden bottleneck discovery:&lt;/strong&gt; Identifies problems in third-party libraries or Node.js code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Superior precision:&lt;/strong&gt; Uses CPU sampling directly, providing more accurate data about actual CPU usage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple metrics:&lt;/strong&gt; Beyond time, can provide data on memory allocation and other aspects&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Use Native CPU Profiling in Meteor
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Basic Configuration
&lt;/h3&gt;

&lt;p&gt;To generate a basic CPU profile, use the &lt;code&gt;METEOR_INSPECT&lt;/code&gt; environment variable specifying which functions you want to profile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Profile a single function&lt;/span&gt;
&lt;span class="nv"&gt;METEOR_INSPECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bundler.bundle meteor build ./output-build

&lt;span class="c"&gt;# Profile multiple functions&lt;/span&gt;
&lt;span class="nv"&gt;METEOR_INSPECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bundler.bundle,compiler.compile meteor build ./output-build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Available Functions for Profiling
&lt;/h3&gt;

&lt;p&gt;Meteor supports profiling for several critical functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;bundler.bundle&lt;/code&gt; - Application packaging process&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;compiler.compile&lt;/code&gt; - General compilation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Babel.compile&lt;/code&gt; - Babel-specific compilation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_readProjectMetadata&lt;/code&gt; - Reading project metadata&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;initializeCatalog&lt;/code&gt; - Package catalog initialization&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_downloadMissingPackages&lt;/code&gt; - Downloading missing packages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_saveChangeMetadata&lt;/code&gt; - Saving change metadata&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_realpath&lt;/code&gt; - File path resolution&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;package-client&lt;/code&gt; - Package client operations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Advanced Configuration Options
&lt;/h3&gt;

&lt;p&gt;You can customize the profiling behavior with additional environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Identifier for profile files&lt;/span&gt;
&lt;span class="nv"&gt;METEOR_INSPECT_CONTEXT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;context_name

&lt;span class="c"&gt;# Directory where .cpuprofile files will be saved (default: ./profiling)&lt;/span&gt;
&lt;span class="nv"&gt;METEOR_INSPECT_OUTPUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/path/to/directory

&lt;span class="c"&gt;# Sampling interval in ms - lower values = more details but uses more memory&lt;/span&gt;
&lt;span class="nv"&gt;METEOR_INSPECT_INTERVAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;500

&lt;span class="c"&gt;# Maximum profile size in MB (default: 2000)&lt;/span&gt;
&lt;span class="nv"&gt;METEOR_INSPECT_MAX_SIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For Large Applications
&lt;/h3&gt;

&lt;p&gt;Larger applications may require more memory for profiling. To avoid out-of-memory (OOM) errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;NODE_OPTIONS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"--max-old-space-size=4096"&lt;/span&gt; &lt;span class="nv"&gt;METEOR_INSPECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bundler.bundle meteor &amp;lt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Analyzing CPU Profiling Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  With Chrome DevTools
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open Chrome DevTools&lt;/li&gt;
&lt;li&gt;Go to the "Performance" or "Profiler" tab&lt;/li&gt;
&lt;li&gt;Click "Load Profile" and select the generated .cpuprofile file&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  With cpupro (Open-Source Visualizer)
&lt;/h3&gt;

&lt;p&gt;For more advanced analysis, you can use &lt;a href="https://discoveryjs.github.io/cpupro/" rel="noopener noreferrer"&gt;cpupro&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visit &lt;a href="https://discoveryjs.github.io/cpupro/" rel="noopener noreferrer"&gt;https://discoveryjs.github.io/cpupro/&lt;/a&gt; in your browser&lt;/li&gt;
&lt;li&gt;Drag and drop your .cpuprofile file onto the interface&lt;/li&gt;
&lt;li&gt;Use the interactive visualization to explore your profile data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;cpupro offers several advantages over Chrome DevTools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better handling of large profiles&lt;/li&gt;
&lt;li&gt;More flexible filtering options&lt;/li&gt;
&lt;li&gt;Advanced search capabilities&lt;/li&gt;
&lt;li&gt;Multiple visualization modes&lt;/li&gt;
&lt;li&gt;Ability to compare different profiles&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Practical Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Identifying Bottlenecks in Template Compilation
&lt;/h3&gt;

&lt;p&gt;If your Meteor application is taking a long time to restart after template changes, you can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;METEOR_INSPECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;compiler.compile meteor run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Analyze the resulting profile to identify which templates are causing the most overhead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagnosing Slow Build Problems
&lt;/h3&gt;

&lt;p&gt;For apps with slow builds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;METEOR_INSPECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bundler.bundle meteor build ./output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look in the profile for functions that are consuming excessive time, such as CSS processing, code transpilation, or minification.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimizing Package Loading
&lt;/h3&gt;

&lt;p&gt;If you suspect packages are affecting performance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;METEOR_INSPECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;_downloadMissingPackages,package-client meteor update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When to Use Each Type of Profiling
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use Meteor's Built-in Profiling (&lt;code&gt;METEOR_PROFILE&lt;/code&gt;) when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You need a quick and general overview of Meteor tool performance&lt;/li&gt;
&lt;li&gt;You're analyzing specific issues in Meteor operations&lt;/li&gt;
&lt;li&gt;You prefer simple text-based reports&lt;/li&gt;
&lt;li&gt;You have limited system resources (less memory usage)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Native CPU Profiling (&lt;code&gt;METEOR_INSPECT&lt;/code&gt;) when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You need more detailed analysis than the standard profiler provides&lt;/li&gt;
&lt;li&gt;You're investigating complex performance issues&lt;/li&gt;
&lt;li&gt;You want to identify specific bottlenecks in heavy functions like bundler or compiler&lt;/li&gt;
&lt;li&gt;You need interactive visualization and in-depth analysis&lt;/li&gt;
&lt;li&gt;You're looking to understand issues in third-party libraries or Node.js runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Real life demo
&lt;/h3&gt;

&lt;p&gt;When using CPU profiling in real Meteor applications, we can identify specific bottlenecks that significantly impact performance. Let's analyze two practical examples:&lt;/p&gt;

&lt;h4&gt;
  
  
  Case 1: Babel as the main CPU consumer
&lt;/h4&gt;

&lt;p&gt;When examining a Meteor CPU profile, we can clearly observe that Babel is the module consuming most of the processing time, both in self time (time spent within the function itself) and total time (time including calls to other functions):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0utl507f9adl3y67dbrr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0utl507f9adl3y67dbrr.png" alt="Image description" width="800" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a known issue in the Meteor community and fortunately it's already being addressed by PRs &lt;a href="https://github.com/meteor/meteor/pull/13675" rel="noopener noreferrer"&gt;#13675&lt;/a&gt; and &lt;a href="https://github.com/meteor/meteor/pull/13674" rel="noopener noreferrer"&gt;#13674&lt;/a&gt;, which aim to replace Babel with SWC, a much faster transpiler written in Rust.&lt;/p&gt;

&lt;p&gt;PR #13675, in particular, implements a smart approach: it uses SWC for initial transpilation, but preserves reify to maintain Meteor-specific features, such as reify modules, nested imports, and top-level await support. This allows gaining speed without losing important functionalities of the Meteor ecosystem.&lt;/p&gt;

&lt;h4&gt;
  
  
  Case 2: Analyzing by Self Time - The bottleneck in compiler-plugin
&lt;/h4&gt;

&lt;p&gt;When sorting the same profile by "self time", we find the "script" module appearing as the one consuming the most processing time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6qq43qriy0km4opbtx5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6qq43qriy0km4opbtx5.png" alt="Image description" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Digging deeper, we see that the &lt;code&gt;compiler-plugin.js&lt;/code&gt; file is responsible for much of this consumption. And digging even deeper, the &lt;code&gt;_linkJS&lt;/code&gt; function stands out as the most expensive of all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmml4foc9zvevun32rnsf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmml4foc9zvevun32rnsf.png" alt="Image description" width="800" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Examining the flame graph of this function, we can see that there is especially intensive processing in the generation of hashes for the cache system:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fnj3cc9tllhx63g7hh4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fnj3cc9tllhx63g7hh4.png" alt="Image description" width="800" height="202"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cacheKeyPrefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sha1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;linkerOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;jsResources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputFile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;fileHashes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;inputFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;meteorInstallOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inputFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meteorInstallOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;absModuleId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inputFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;absModuleId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;sourceMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;inputFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sourceMap&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;mainModule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inputFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mainModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;imported&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inputFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;imported&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inputFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inputFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;bare&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inputFile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bare&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cacheKeySuffix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sha1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;LINKER_CACHE_SALT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;fileHashes&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This snippet shows that for each JavaScript file processed, the function executes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Multiple &lt;code&gt;await&lt;/code&gt; operations to access properties like &lt;code&gt;hash&lt;/code&gt; and &lt;code&gt;sourceMap&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Conversions to JSON (via &lt;code&gt;JSON.stringify&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Multiple SHA-1 hash calculations&lt;/li&gt;
&lt;li&gt;Promise operations that occur for each file individually&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The impact of this code is significant because it is executed for each JavaScript file in each module/package, becoming a serious bottleneck in larger applications with many files. Each call of this function processes all files again to generate cache keys, even when most files haven't changed.&lt;/p&gt;

&lt;p&gt;This is an area where focused optimization could bring significant benefits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;While Meteor's built-in profiling system offers a more practical solution for performance analysis, native CPU profiling based on Node.js Inspector provides deeper and more detailed insights into your application's build performance. By combining both approaches, Meteor developers can identify and solve performance problems with unprecedented precision.&lt;/p&gt;

&lt;p&gt;Try these techniques in your next performance debugging session and see how CPU profiling can transform your approach to optimizing Meteor applications. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Unlocking Meteor 3.2: New Profiling Tool to Track Bundler Performance and Size</title>
      <dc:creator>Nacho Codoñer</dc:creator>
      <pubDate>Thu, 20 Mar 2025 16:37:38 +0000</pubDate>
      <link>https://forem.com/meteor/unlocking-meteor-32-new-profiling-tool-to-track-bundler-performance-and-size-1jc8</link>
      <guid>https://forem.com/meteor/unlocking-meteor-32-new-profiling-tool-to-track-bundler-performance-and-size-1jc8</guid>
      <description>&lt;p&gt;Meteor continues to evolve. After focusing on improving runtime performance, the latest update, Meteor 3.2, pivots toward bundler performance and optimizing the developer experience.&lt;/p&gt;

&lt;p&gt;With Meteor 3.2, we introduced profiling. We revisited the old implementation to restore functionality and added &lt;code&gt;meteor profile&lt;/code&gt; for automatic analysis of the app build process. This tool helps you track critical data like build phase timings and bundle sizes, which are key for optimizing performance and reducing build times.&lt;/p&gt;

&lt;p&gt;This marks the beginning of exciting improvements to Meteor’s bundler, as we integrate modern solutions while maintaining Meteor’s performance and developer-friendly experience. Whether you’re working on a private project or contributing to the Meteor core, the new &lt;code&gt;meteor profile&lt;/code&gt; tool is here to help you monitor and optimize the app’s build process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started: A Quick Hands-On
&lt;/h2&gt;

&lt;p&gt;Ready to dive in? To start using the new profiling tool, ensure your app is on Meteor 3.2 (or create a new one).&lt;/p&gt;

&lt;h3&gt;
  
  
  Update Your App
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Update your existing Meteor app to version 3.2&lt;/span&gt;
meteor update &lt;span class="nt"&gt;--release&lt;/span&gt; 3.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a New App
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a new Meteor app using Meteor 3.2&lt;/span&gt;
meteor create meteorite-app &lt;span class="nt"&gt;--release&lt;/span&gt; 3.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Profiling Your App’s Development Process
&lt;/h3&gt;

&lt;p&gt;The key to Meteor 3.2's new profiling feature is the &lt;code&gt;meteor profile&lt;/code&gt; command. Here’s how you can run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;meteor profile &lt;span class="o"&gt;[&lt;/span&gt;&amp;lt;meteor-run-options&amp;gt;...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command tracks the time taken across various phases of running your Meteor app, capturing insights that will help you fine-tune performance.&lt;/p&gt;

&lt;h4&gt;
  
  
  Here’s a Breakdown of the Profiling Phases:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cold Start&lt;/strong&gt;: This is the first run of your app, when no data is cached in the &lt;code&gt;.meteor/local&lt;/code&gt; folder. (Use &lt;code&gt;meteor reset&lt;/code&gt; to simulate this phase.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache Start&lt;/strong&gt;: The second run, where the app leverages cached data, improving startup speed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rebuild Client&lt;/strong&gt;: When you change client-side code, this phase measures the time required to rebuild the client-side app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rebuild Server&lt;/strong&gt;: Similar to the client rebuild, but this tracks the time to rebuild the server-side code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these key phases, you can easily track how your app’s performance changes as you make updates.&lt;/p&gt;

&lt;p&gt;Here’s an example output from the small-sized Meteor React example, to see what it looks like in action:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqrtk0t6fh3l2kmfzzsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqrtk0t6fh3l2kmfzzsj.png" alt="profiling-dev" width="474" height="866"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A detailed log is generated during profiling, which you’ll find in the &lt;code&gt;logs&lt;/code&gt; folder. This log contains full &lt;code&gt;meteor run&lt;/code&gt; and &lt;code&gt;METEOR_PROFILE&lt;/code&gt; output for each phase. Feel free to adjust the &lt;a href="https://docs.meteor.com/cli/environment-variables#meteor-profile" rel="noopener noreferrer"&gt;&lt;code&gt;METEOR_PROFILE&lt;/code&gt; environment variable&lt;/a&gt; to suit your needs. For more options, run &lt;code&gt;meteor profile --help&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Profiling Your App’s Size
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;meteor profile&lt;/code&gt; command can also help you track bundle sizes. Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;meteor profile --size-only [&amp;lt;meteor-run-options&amp;gt;...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command provides a breakdown of the package sizes across different bundlers, such as Meteor Modern, Legacy, and Cordova, helping you identify optimization opportunities. You’ll see the results in a neat table format, making it easy to spot potential issues.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi9i8non3vz3w01bp11jb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi9i8non3vz3w01bp11jb.png" alt="profiling-size" width="800" height="880"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to include bundle size analysis as part of a full profiling session, simply add the &lt;code&gt;--size&lt;/code&gt; option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tip: Exclude Architectures for a Faster Dev Experience
&lt;/h2&gt;

&lt;p&gt;Here’s a quick tip to improve your development speed. If you’re not targeting legacy browsers or Cordova, you can exclude those architectures to speed up builds.&lt;/p&gt;

&lt;p&gt;For example, compare the default behavior with excluding certain architectures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1) `meteor run`&lt;/span&gt;
meteor profile

&lt;span class="c"&gt;# 2) `meteor run` excluding certain archs&lt;/span&gt;
meteor profile &lt;span class="nt"&gt;--exclude-archs&lt;/span&gt; web.browser.legacy,web.cordova
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output comparison for the small-sized Meteor React example is shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flic5mknfgo886ke0u6py.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flic5mknfgo886ke0u6py.png" alt="default-vs-exclude-archs" width="800" height="621"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The impact will be much greater on large, full-featured apps. By excluding legacy and Cordova builds, you can see reduction in build times, especially when restarting Meteor apps ("Build App" stage in profile). These architectures are useful for testing older browsers or building for Cordova, but they’re often unnecessary during regular development, especially if you’re targeting modern browsers or platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next for Meteor and Beyond?
&lt;/h2&gt;

&lt;p&gt;Meteor 3.2 sets the stage for future improvements. The new &lt;code&gt;meteor profile&lt;/code&gt; command helps ensure performance gains or size reductions without regressions. Automated profiling replaces subjective assessments with data-driven releases, now available to all Meteor developers.&lt;/p&gt;

&lt;p&gt;Upcoming improvements to the Meteor bundler include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/meteor/meteor/pull/13657" rel="noopener noreferrer"&gt;&lt;strong&gt;SWC Support&lt;/strong&gt;&lt;/a&gt;: We’re working on integrating SWC for enhanced compilation and analysis capabilities.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/meteor/meteor/pull/13650" rel="noopener noreferrer"&gt;&lt;strong&gt;CPU Profiling and Memory Snapshots&lt;/strong&gt;&lt;/a&gt;: This will allow for deeper performance tuning across all phases of app building.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modern Bundler Integration&lt;/strong&gt;: Expect improved bundler features and faster speeds with the adoption of modern bundlers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default Modern Architecture&lt;/strong&gt;: Soon, Meteor will build only for modern architecture by default, skipping legacy and Cordova builds unless you specify otherwise.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These improvements will help keep Meteor aligned with current standards on the bundler side while improving performance and developer experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Else Is New in Meteor 3.2?
&lt;/h2&gt;

&lt;p&gt;Meteor 3.2 brings more than just new profiling tools. Want to explore further?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://forums.meteor.com/t/meteor-js-v3-2-is-out/63368" rel="noopener noreferrer"&gt;Join the Conversation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=YufS7h6_joM" rel="noopener noreferrer"&gt;Watch the Discussion&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Join the Meteor Renaissance!
&lt;/h2&gt;

&lt;p&gt;Meteor 3.2 brings a new era of profiling tools, allowing developers to monitor app performance and bundle size like never before. With these updates, you’ll have the insights needed to optimize your app’s performance with data-driven decisions.&lt;/p&gt;

&lt;p&gt;We’re excited about what’s to come and can’t wait for you to join the Meteor renaissance!&lt;/p&gt;

&lt;p&gt;For feedback, questions, or support, &lt;a href="https://forums.meteor.com/" rel="noopener noreferrer"&gt;visit our forums&lt;/a&gt; or &lt;a href="https://discord.com/invite/3w7EKdpghq" rel="noopener noreferrer"&gt;join our Discord channel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Follow us on &lt;a href="https://x.com/meteorjs" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://github.com/meteor" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Stay tuned, and as always, happy coding! ☄️&lt;/p&gt;

</description>
      <category>meteor</category>
      <category>javascript</category>
      <category>performance</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The Meteor 3.0 Migration: A Space Exploration Mission</title>
      <dc:creator>Harry Adel</dc:creator>
      <pubDate>Tue, 18 Mar 2025 16:05:29 +0000</pubDate>
      <link>https://forem.com/meteor/the-meteor-30-migration-a-space-exploration-mission-3gb5</link>
      <guid>https://forem.com/meteor/the-meteor-30-migration-a-space-exploration-mission-3gb5</guid>
      <description>&lt;p&gt;Just wanted to share this story of how we completed our Meteor 3.0 migration at my company &lt;a href="https://www.medbeauty.com/" rel="noopener noreferrer"&gt;medbeauty&lt;/a&gt; and how more than a year's worth of effort is coming to an end with a PR of 439 file changes about to be merged 🤞&lt;/p&gt;

&lt;h2&gt;
  
  
  Mission Briefing: The Launch Preparation
&lt;/h2&gt;

&lt;p&gt;A little background on the application: it was started in 2014. In my humble opinion, it's one of the last OG Meteor fortresses as it still utilizes Blaze &amp;amp; Cordova. Full-stack reactivity all the way thanks to &lt;a href="https://github.com/dburles/meteor-collection-helpers" rel="noopener noreferrer"&gt;collection-helpers&lt;/a&gt;. It's about as OG as you can get. &lt;/p&gt;

&lt;h2&gt;
  
  
  Liftoff: Initial Trajectory Calculations
&lt;/h2&gt;

&lt;p&gt;The team at medbeauty had already dipped their toes in the 3.0 waters as their migration efforts began in 2023 while I joined them late January 2024. They had migrated lots of bits to async. Even &lt;a href="https://github.com/danieldornhardt" rel="noopener noreferrer"&gt;DanielDornhardt&lt;/a&gt; had created a magnificent &lt;a href="https://forums.meteor.com/t/blaze-async-migration-helper-babel-plugin-tracker-async-enhance-for-the-client-side-released/60842" rel="noopener noreferrer"&gt;babel-plugin&lt;/a&gt; (which isn't getting the credit it deserves, by the way) to help keep your Blaze code looking nice while migrating it to async.&lt;/p&gt;

&lt;p&gt;Since I had already been involved in the Meteor community, I had been getting notifications in my email with the PRs that were popping up here and there, but didn't see anything materialize. The core team was hammering away at the core packages, but no love was being shown to Atmosphere packages. After all, a framework is only as good as its surrounding ecosystem—no wonder people were ditching Blaze for React!&lt;/p&gt;

&lt;p&gt;I was already skeptical of such an endeavor and didn't even know if it was feasible. So I started with what I know best: Collection2!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Launch Sequence: Igniting Collection2
&lt;/h2&gt;

&lt;p&gt;I believe Collection2 is one of those very few packages that act as a cornerstone for the entire Meteor framework. If these packages could be made async-friendly, then the rest would surely follow.&lt;/p&gt;

&lt;p&gt;A little side trivia: I never anticipated nor vowed to undertake maintaining Collection2. Back when MCP was just getting started, I created an &lt;a href="https://github.com/Meteor-Community-Packages/organization/issues/29" rel="noopener noreferrer"&gt;issue&lt;/a&gt; suggesting including the package in the roster due to its importance and the fact that Eric/&lt;a href="https://github.com/aldeed" rel="noopener noreferrer"&gt;Aldeed&lt;/a&gt; had already moved beyond Meteor. Once the package was moved, I was surprised that StorytellerCZ granted me maintainer access. In hindsight, it was a great decision ;)&lt;/p&gt;

&lt;p&gt;Back to Collection2, work had already &lt;a href="https://github.com/Meteor-Community-Packages/meteor-collection2/pull/443" rel="noopener noreferrer"&gt;started&lt;/a&gt; thanks to &lt;a href="https://github.com/klablink" rel="noopener noreferrer"&gt;Klablink&lt;/a&gt;—big shoutout to him as he helped with many packages. I started a PR &lt;a href="https://github.com/Meteor-Community-Packages/meteor-collection2/pull/444" rel="noopener noreferrer"&gt;building&lt;/a&gt; on his work and went from there. Bit by bit, I began to understand the changes made and even tried to improve it and cut down on the code changes. This was also the first time in my life where I had released a beta version of Meteor packages (I didn't know if it was even possible, but hey, we keep on learning).&lt;/p&gt;

&lt;p&gt;I kept modifying code &amp;amp; releasing betas, then modifying the package in our application to see if anything would break. Also, Andrei/&lt;a href="https://github.com/alisnic" rel="noopener noreferrer"&gt;alisnic&lt;/a&gt; came to the &lt;a href="https://github.com/Meteor-Community-Packages/meteor-collection2/pull/444#issuecomment-1870149278" rel="noopener noreferrer"&gt;rescue&lt;/a&gt;. With 2400 unit tests and 821 e2e test cases, surely I didn't break anything, right?&lt;/p&gt;

&lt;p&gt;After a couple of hiccups and many commits, we made it! &lt;a href="https://github.com/Meteor-Community-Packages/meteor-collection2/pull/444#issuecomment-1898346301" rel="noopener noreferrer"&gt;4.0.0&lt;/a&gt; was released, affirming the possibility of not only migrating Meteor packages—but in my own eyes—Meteor and Meteor projects as a whole.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entering Orbit: Community Navigation Challenges
&lt;/h2&gt;

&lt;p&gt;This experience had not only proven the possibility but also revealed the amount of work that awaited us. It highlighted a problem with the coordination of the community because I had seen people not only replicating work but also migrating silently or forking packages entirely! Which could bring an end to this unborn endeavor entirely!&lt;/p&gt;

&lt;p&gt;That's why after brief discussions with Daniel, we came up with the idea to document the packages that needed to be migrated and their current status. This eventually led to the birth of this forum &lt;a href="https://forums.meteor.com/t/looking-for-help-migrating-packages-to-meteor-3-0/60985" rel="noopener noreferrer"&gt;article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The forum post helped to showcase who was working on what and gave a sense of how things were moving. While I had hoped for more widespread community participation to distribute the workload, the reality was that the effort largely fell to a dedicated group of familiar faces along with a few new contributors. When I shared my thoughts with &lt;a href="https://github.com/alimgafar" rel="noopener noreferrer"&gt;alimgafar&lt;/a&gt; about wanting more community involvement, he offered a perspective that resonated with me: "that's how open source™ works" – a small group of passionate contributors often carries the weight of major transitions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ymwj0u0x6azzil8n7kh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ymwj0u0x6azzil8n7kh.png" alt="Jan brothers" width="770" height="978"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Needless to say, medbeauty &amp;amp; Daniel were both gracious with their time and monetary support. At one point, Daniel even instructed me to take a pause and &lt;a href="https://forums.meteor.com/t/looking-for-help-migrating-packages-to-meteor-3-0/60985/39?u=harry97" rel="noopener noreferrer"&gt;create PRs&lt;/a&gt; for the packages that we had migrated so others could benefit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gravitational Anomalies: Deployment Mysteries
&lt;/h2&gt;

&lt;p&gt;As we migrated more and more packages and made significant improvements to our codebase, we became increasingly confident in our ability to increase the version number.&lt;/p&gt;

&lt;p&gt;One of the most intriguing things that stood out to me during this phase was that we ran into troubles when we tried building and deploying our Meteor application. The problem had already been &lt;a href="https://github.com/meteor/meteor/issues/12932" rel="noopener noreferrer"&gt;reported&lt;/a&gt; by &lt;a href="https://github.com/zodern" rel="noopener noreferrer"&gt;zodern&lt;/a&gt;, and surprisingly, we were the third to comment on it!&lt;/p&gt;

&lt;p&gt;By that time, I had read countless articles here on the forums about how people had migrated to the lush green 3.0 lands, yet I was left puzzled. If so many teams had successfully made the journey, I wondered why more weren't encountering this deployment issue. I began to question whether there was a difference between production-grade applications with paying customers versus smaller projects with less complex requirements. The contrast between reported experiences and our own challenges made me curious about what we might be missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Course Corrections: Navigation Adjustments
&lt;/h2&gt;

&lt;p&gt;Migrating packages was no easy task. At times, we had to make course corrections and prioritize getting things working instead of getting things right.&lt;/p&gt;

&lt;p&gt;I had to make adjustments and make the best of the current situation, which is why I opted to still use node-sass in fourseven:scss instead of switching to &lt;a href="https://github.com/leonardoventurini/meteor-scss" rel="noopener noreferrer"&gt;leonardoventurini:scss&lt;/a&gt;. I had &lt;a href="https://github.com/Meteor-Community-Packages/meteor-scss/pull/321#issue-2307741493" rel="noopener noreferrer"&gt;recommended&lt;/a&gt; forking and modifying a core package just to make things work.&lt;/p&gt;

&lt;p&gt;But this experience didn't come easily. I had burned weeks on end trying to perfect the packages we're using. I had to freeze a version of collection-hooks that's compatible with our code. I commented out pieces of code that utilized autoValue, which still is &lt;a href="https://github.com/Meteor-Community-Packages/meteor-simple-schema/pull/746" rel="noopener noreferrer"&gt;in the works&lt;/a&gt;. And I think that's the moral of the story I want to drive home: it takes time, there's no perfect flight path, and you have to make some navigational adjustments.&lt;/p&gt;

&lt;p&gt;Thankfully, many commits later, our application is stable and deployed to production, but there's still remaining work for us as we're still facing &lt;a href="https://github.com/meteor/meteor/issues/13474" rel="noopener noreferrer"&gt;problems&lt;/a&gt; with Cordova. We're currently considering our options of soliciting outside help, so maybe there will be a part 2?&lt;/p&gt;

&lt;h2&gt;
  
  
  Mission Data: Exploration Statistics
&lt;/h2&gt;

&lt;p&gt;Did you like my storytelling talents? Call me StorytellerEG — because clearly the pyramids make for better storytelling backdrops than Prague Castle!&lt;/p&gt;

&lt;p&gt;Now time for some fun mission statistics for those interested:&lt;/p&gt;

&lt;p&gt;A picture is worth 1000 words:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwi71qcz23343kpaufxz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwi71qcz23343kpaufxz.png" alt="tiny PR" width="800" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;250 commits (tens of them were trying to re-run the CI actually)&lt;/li&gt;
&lt;li&gt;439 changed files (200 forked packages?)&lt;/li&gt;
&lt;li&gt;2 Conversations (I'm a man of few words)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the way, we had started and closed multiple PRs in the hopes of merging 3.0, so this is probably the 3rd clone with plenty of merged/squashed commits with multiple mini-PRs already merged in, so the amount of code we changed is larger than what's mentioned in this image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mission Control's Transmission: Guidance for Future Explorers
&lt;/h2&gt;

&lt;p&gt;Since I grew a single grey hair during this migration, this warrants me transmitting wisdom to all you young space cadets out there on how to migrate your applications. So ditch your flight manuals and come listen to how seasoned astronauts do it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test Your Life Support Systems&lt;/strong&gt;: Time and time again, I've been proven that if you were to boil down all of the best practices of software development, it just comes down to having tests. If you don't have a robust test suite with plenty of coverage, then you might want to start investing in it immediately. Otherwise, suck to be you, sorry 🤷‍♂️ &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Don't Jump to Warp Speed Immediately&lt;/strong&gt;: Don't kick off your application by pumping it to 3.0 like I did. I thought, "Hey, I'd just increase the version number and go from there fixing errors bit by bit and getting it working." WRONG!&lt;/p&gt;

&lt;p&gt;Again, I learned this the hard way. I tried and failed, or better yet, didn't even get to try because as I attempted to run &lt;code&gt;meteor update --release 3.x&lt;/code&gt;, it crashed with the following &lt;a href="https://github.com/meteor/meteor/issues/12902" rel="noopener noreferrer"&gt;error&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MINISAT-out: Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value 67108864, (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.
MINISAT-err: Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value 67108864, (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.
abort() at Error                              
    at jsStackTrace (packages/logic-solver.js:21:18626)
    at stackTrace (packages/logic-solver.js:21:18809)
    at abort (packages/logic-solver.js:51:28956)
    at enlargeMemory (packages/logic-solver.js:21:19142)
    at Function.dynamicAlloc [as alloc] (packages/logic-solver.js:21:7927)
    at _sbrk (packages/logic-solver.js:21:58803)
    at Sd (packages/logic-solver.js:25:98389)
    at Ud (packages/logic-solver.js:25:109800)
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;This is what pushed me into dissecting this into small pieces and starting this whole 3.0 libraries migration thread.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Install Your Warning System&lt;/strong&gt;: Enable the &lt;code&gt;WARN_WHEN_USING_OLD_API&lt;/code&gt; env variable. It's a little env variable that got added during &lt;a href="https://guide.meteor.com/2.12-migration" rel="noopener noreferrer"&gt;2.12&lt;/a&gt; but didn't get much attention. Enabling it should be your first pre-flight check.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gradual Engine Upgrades&lt;/strong&gt;: Once you've enabled it, slowly start migrating all of your old DB calls to async.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Replace Components Methodically&lt;/strong&gt;: As you're doing the previous step, you might need to start swapping out the old Meteor packages with the new ones. Act accordingly and, most importantly, &lt;em&gt;patiently&lt;/em&gt;. You don't want to introduce too many changes at once; that's how you crash your spacecraft. Don't ask how I know.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiple Small Launches Beat One Big One&lt;/strong&gt;: Introduce changes in small, separate PRs as much as you can. We migrated all our packages and DB calls before launching into the final frontier—err, 3.0, I mean.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Share Your Flight Log&lt;/strong&gt;: Share your experience and stay in touch. It helped me immensely that I was cross-referencing many ideas with the community and reporting any issues back to mission control. In a way, this article is part of this migration journey so we can collectively learn and elevate each other.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Mission Accomplished: Return to Earth
&lt;/h2&gt;

&lt;p&gt;After more than a year of work, our Meteor 3.0 migration is complete and running in production. This achievement wouldn't have been possible without the support of the open source community.&lt;/p&gt;

&lt;p&gt;Special thanks to &lt;a href="https://github.com/klablink" rel="noopener noreferrer"&gt;Klablink&lt;/a&gt;, &lt;a href="https://github.com/bhunjadi" rel="noopener noreferrer"&gt;bhunjadi&lt;/a&gt;, &lt;a href="https://github.com/alisnic" rel="noopener noreferrer"&gt;alisnic&lt;/a&gt;, &lt;a href="https://github.com/bratelefant" rel="noopener noreferrer"&gt;bratelefant&lt;/a&gt;, &lt;a href="https://github.com/vparpoil" rel="noopener noreferrer"&gt;vparpoil&lt;/a&gt;, &lt;a href="https://github.com/leonardoventurini" rel="noopener noreferrer"&gt;leonardoventurini&lt;/a&gt;, &lt;a href="https://github.com/dr-dimitru" rel="noopener noreferrer"&gt;dr-dimitru&lt;/a&gt;, and &lt;a href="https://github.com/paulincai" rel="noopener noreferrer"&gt;paulishca&lt;/a&gt; who contributed critical components to this ecosystem-wide effort. I apologize if I forgot any names.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96v1jqjvhryv4lnjygr7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96v1jqjvhryv4lnjygr7.png" alt="Your #1 Meteor expert" width="500" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you'd like help migrating to 3.0 or generally would like to connect and chat about your own space mission, I've set up a &lt;a href="https://cal.com/harryadel" rel="noopener noreferrer"&gt;cal&lt;/a&gt; account.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Migrating to Meteor 3: a solo developer story</title>
      <dc:creator>Dominic Thwaites</dc:creator>
      <pubDate>Thu, 13 Mar 2025 18:25:48 +0000</pubDate>
      <link>https://forem.com/meteor/migrating-to-meteor-3-a-solo-developer-story-1nek</link>
      <guid>https://forem.com/meteor/migrating-to-meteor-3-a-solo-developer-story-1nek</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;My Meteor 3 conversion story starts October 2023 and ends Spring 2025.&lt;/p&gt;

&lt;p&gt;Apart from achieving future-proofness with Meteor 3, the upgrade has also caused/motivated me to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upgrade all 3rd party libraries to latest versions&lt;/li&gt;
&lt;li&gt;Establish unit tests for all methods and subscriptions that perform basic sanity and security checks on all of them&lt;/li&gt;
&lt;li&gt;Make other changes that generally improve reliability, performance,  standardisations and code clarity&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So while it's been a lot of work, it's been worth it!&lt;/p&gt;

&lt;h2&gt;
  
  
  About me
&lt;/h2&gt;

&lt;p&gt;I'm a semi-retired IT professional who used to work in the banking industry building real-time trading systems. Things are different now, but back in the day, reactivity was rare in applications and our systems in banking were all home grown reactive applications (we're talking 20+ years ago). I've always been intrigued about how to build systems that reflected their data state seamlessly &amp;amp; continuously. Anyway, I left banking a while ago and consulted for the most part. I'm an active squash player at my local club and wasn't impressed with the systems available to manage the processes involved for members and the club, so I started to build &lt;a href="http://www.managemymatch.com" rel="noopener noreferrer"&gt;ManageMyMatch&lt;/a&gt; in 2017 having identified Meteor as an interesting framework to work with. And so my Meteor journey began...&lt;/p&gt;

&lt;h2&gt;
  
  
  The app
&lt;/h2&gt;

&lt;p&gt;The app is a club management system for racquet sports (Squash, Tennis etc). Size-wise we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;730 Template files&lt;/li&gt;
&lt;li&gt;1,500 JS files&lt;/li&gt;
&lt;li&gt;115,000 JS source code lines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having completed the conversion we have 3,236 Meteor async calls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1,500 findOneAsync()&lt;/li&gt;
&lt;li&gt;320 fetchAsync()&lt;/li&gt;
&lt;li&gt;64 insertAsync()&lt;/li&gt;
&lt;li&gt;836 updateAsync()&lt;/li&gt;
&lt;li&gt;75 removeAsync()&lt;/li&gt;
&lt;li&gt;47 forEachAsync()&lt;/li&gt;
&lt;li&gt;294 mapAsync()&lt;/li&gt;
&lt;li&gt;96 countAsync()&lt;/li&gt;
&lt;li&gt;4 observeAsync()&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Client/server interface&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;519 Meteor methods&lt;/li&gt;
&lt;li&gt;206 publications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My app uses Blaze as well as dozens of 3rd party packages some of which required custom upgrade to get them to work again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary &amp;amp; general approach
&lt;/h2&gt;

&lt;p&gt;It took about 8 months of solid work to complete. Half of that is testing. We're still not done with testing actually - but we are in user acceptance stage now. There were two phases to the plan (about 4 man-months each):&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-meteor 3 upgrade
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Convert all relevant functions to async&lt;/li&gt;
&lt;li&gt;Build unit tests for every meteor method &amp;amp; publication&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Post-meteor 3 upgrade
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Remove, re-install &amp;amp; upgrade all 3rd party packages to latest versions&lt;/li&gt;
&lt;li&gt;Get the client app back up and running&lt;/li&gt;
&lt;li&gt;Perform integration testing&lt;/li&gt;
&lt;li&gt;Perform user acceptance testing&lt;/li&gt;
&lt;li&gt;Rollout &amp;amp; re-issue iOS &amp;amp; Android apps&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pre-meteor 3 upgrade
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Async conversion
&lt;/h3&gt;

&lt;p&gt;I did initially use a &lt;a href="https://github.com/minhna/meteor-async-migration" rel="noopener noreferrer"&gt;codemon&lt;/a&gt; to start the process but it rapidly became clear that the impact of asyncing had to be dealt with by hand in every file. So it was a long trawl. Every change meant iterating up the function call tree to async functions were necessary. In doing so there were two main categories of issues:&lt;/p&gt;

&lt;h3&gt;
  
  
  Isomorphic code
&lt;/h3&gt;

&lt;p&gt;I have lots of isomorphic code (runs on client and server) and ending up with async template helpers is far from ideal. I needed to minimise the amount of async that ended up in the client. I generally had these scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Collection helpers: (I use &lt;code&gt;dburles:collection-helpers&lt;/code&gt;) I ended up creating two versions where necessary. &lt;code&gt;Collection.helperXyzAsync()&lt;/code&gt; declared in a server folder so the server would use that and &lt;code&gt;Collection.helperXyz()&lt;/code&gt; declared in a client folder so the client would use that.&lt;/li&gt;
&lt;li&gt;I stubbed out many meteor methods preventing them from running optimistically on the client and then imported the files that contained async methods at the top of the method function. This process allowed me to audit and refactor what really needed to be isomorphic and has reduced my client footprint&lt;/li&gt;
&lt;li&gt;In the same vein, I audited and segregated dozens of general helper functions for server or client use.&lt;/li&gt;
&lt;li&gt;In some instances, where I had a pseudo package of isomorphic functionality, I restructured things to encapsulate the async requirement into one initialiser (essentially an &lt;code&gt;async init()&lt;/code&gt; method on a class that encapsulated the functionality). Performance was improved as a happy side product.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  JS iterators
&lt;/h3&gt;

&lt;p&gt;In many, many cases, I needed to put async inside standard JS iterators like &lt;code&gt;forEach()&lt;/code&gt;, &lt;code&gt;map()&lt;/code&gt;, &lt;code&gt;find()&lt;/code&gt;, &lt;code&gt;filter()&lt;/code&gt;.  You can't do that as the function itself doesn't magically become async if the iterator function is async. In every case, I had to refactor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I have pretty much deprecated the use of &lt;code&gt;forEach()&lt;/code&gt; in favour of &lt;code&gt;for (value of array) {...}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For &lt;code&gt;map()&lt;/code&gt;, you could wrap it with &lt;code&gt;Promise.all()&lt;/code&gt;, so &lt;code&gt;let result=a.map(item =&amp;gt; fn(item))&lt;/code&gt; becomes &lt;code&gt;let result=Promise.all(a.map(async item =&amp;gt; fn(item)))&lt;/code&gt;. For larger arrays though, I tended to iterate using &lt;code&gt;for...of&lt;/code&gt; and pushed each result into a predefined result array&lt;/li&gt;
&lt;li&gt; For &lt;code&gt;find()&lt;/code&gt; I replaced it with &lt;code&gt;for...of&lt;/code&gt; and setting an external variable with the found result and &lt;code&gt;break&lt;/code&gt;ing out&lt;/li&gt;
&lt;li&gt; For &lt;code&gt;filter()&lt;/code&gt; I went &lt;code&gt;for...of&lt;/code&gt; route as per &lt;code&gt;map()&lt;/code&gt; though I have done this sometimes: &lt;code&gt;let result=a.filter(item =&amp;gt;!!fn(item))&lt;/code&gt; became &lt;code&gt;let result=_.compact(Promise.all(a.map(async item =&amp;gt; await fn(item) ? item : null)))&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Unit testing
&lt;/h2&gt;

&lt;p&gt;When I started this project I was full of good intentions and wrote some tests. Didn't last long. And, to be honest, I've not regretted it as I am pretty diligent with making sure that what I write works. Bugs exist, of course, but it's not perceived as any kind of issue by my users. But I could have used them for this migration. So I really felt like I needed to thoroughly test my methods and publications having made material changes to pretty much every single one. Besides, my async conversion efforts above had, for various reasons, left my app unrunnable. In order to get decent coverage the data setup requirement was challenging. I've ended up with different approaches for my publication unit tests and my method unit tests.&lt;/p&gt;

&lt;p&gt;As a result I have thousands of sanity &amp;amp; security tests that cover about 90% of all server code and most isomorphic code. And I could now prove the sanity of my conversion work before I could get the app back up and running.&lt;/p&gt;

&lt;p&gt;At first the process of building up the tests was slow as I iterated and improved the auto-generation processes and testing framework. By the end it's all very self generating and it's now very simple (mostly just one line of code) to set a test in place for new subscriptions or methods - so even I might keep up with that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Publication testing
&lt;/h3&gt;

&lt;p&gt;Using &lt;code&gt;dburles:factory&lt;/code&gt; and by calling relevant meteor methods in my app, I built up a variety of different data models that I could instantiate prior to a batch of tests. The database consists of around 50 collections some of which have deeply nested document structures. These needed to be richly instantiated for the publication tests to be meaningful. I used coverage tools to check that I was running most of the code - I achieved about 90% on average. My publications are grouped in about 25 files so I have a test file matching each. I have a common procedure to run several tests per publication that includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anonymous access&lt;/li&gt;
&lt;li&gt;Unauthorised access&lt;/li&gt;
&lt;li&gt;Authorised access&lt;/li&gt;
&lt;li&gt;Bad parameters&lt;/li&gt;
&lt;li&gt;No parameters&lt;/li&gt;
&lt;li&gt;Good parameters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This standardisation has ensured I have a consistent security policy for each and every one. For each publication I encode the expected results in terms of what collections are expected to be returned, how many documents in each and how many properties on those documents are expected. They do not check any more semantics than that or other data content. The key aim is to "sanity" check them and get code coverage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method testing
&lt;/h3&gt;

&lt;p&gt;The database seeding I had for publications was not enough for methods. So I developed a new strategy. All my collections are fully "documented" using &lt;code&gt;aldeed:simple-schema&lt;/code&gt;. I have also augmented SimpleSchema to allow me to annotate foreign keys. So I know what collection every foreign key points to. The parameters to my methods are also documented with SimpleSchema in the same way (foreign keys are identified). With this, I can inspect the schema and auto-generate all documents inferred from the parameters as well as any documents I know the method would expect. Surprisingly this automatically achieves sufficient seeding to attain my 90% coverage target. As with publications, I have coded the generation of the tests to include similar scenarios as listed for publication above.&lt;/p&gt;

&lt;p&gt;Sample documents are auto generated for every test. For example if my method has the parameter &lt;code&gt;{matchId: 'osHdQsYsrvKYzqcBn'}&lt;/code&gt; the test knows this points to my Matches collection and, using the schema, generates a sample Match document. In turn the Match document has several id's that reference documents in other collections. Again, SimpleSchema tells me what collections they are and so I can generate sample documents for those too. And so on. Thus a complete network of documents is self-prepared for the method function to work on. I have special configuration properties that allow me to easily override and specify specific values for certain document properties (otherwise, values are generated that conform to the SimpleSchema type and definitions) in order to emulate certain scenarios to boost coverage. I can also instruct the test to auto generate other documents as needed. The downside is that this data seeding happens for every individual test and there are thousands of them so the whole test run takes about 15 minutes!&lt;/p&gt;

&lt;p&gt;I use &lt;code&gt;mdg:validated-method&lt;/code&gt; and whilst the &lt;code&gt;validate()&lt;/code&gt; function simply checks the syntax of the parameters passed I have an internal, custom validator that is called in every method that also checks on security access and even the validity of foreign keys passed. As a convenience, incidentally, this internal validator returns the documents associated with any foreign keys passed - and most of my methods involve the submission of at least one id field.&lt;/p&gt;

&lt;h2&gt;
  
  
  Post Meteor upgrade
&lt;/h2&gt;

&lt;p&gt;With my app completely disabled, but with all the conversion and refactoring supposedly done it was time to upgrade to Meteor 3. Which of course didn't work as my dependencies were totally shot. So I made careful notes of my packages and removed every one of them (at least all the non standard Meteor ones). Eventually Meteor  allowed me to upgrade.&lt;/p&gt;

&lt;p&gt;Next I started the process of reinstalling all my packages. Many of them didn't work and some of them had breaking changes which necessitated more changes to my code. Others I had to investigate alternatives for. So it took a while to put back together. The biggest of these was &lt;code&gt;aldeed:simple-schema&lt;/code&gt; where I went from version 1 to 2. I have hundreds of schema definitions and they all had to be refactored. I've also ended up having to fork more packages to make dependency adjustments and/or code changes to get them to work with Meteor 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  Package upgrade inventory
&lt;/h2&gt;

&lt;p&gt;Here are all the packages (except for ones I wrote myself for the project). I had forked a few before for functional reasons, but I've had to fork quite a few more now...&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What I had before&lt;/th&gt;
&lt;th&gt;What I have now&lt;/th&gt;
&lt;th&gt;Action or Issues&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:meteor-base@1.5.1"&gt;meteor-base@1.5.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:meteor-base@1.5.2"&gt;meteor-base@1.5.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:mobile-experience@1.1.0"&gt;mobile-experience@1.1.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:mobile-experience@1.1.2"&gt;mobile-experience@1.1.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:mongo@1.16.7"&gt;mongo@1.16.7&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:mongo@2.1.0"&gt;mongo@2.1.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:blaze-html-templates@1.2.1"&gt;blaze-html-templates@1.2.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:blaze-html-templates@3.0.0"&gt;blaze-html-templates@3.0.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:reactive-var@1.0.12"&gt;reactive-var@1.0.12&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:reactive-var@1.0.13"&gt;reactive-var@1.0.13&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:jquery@1.11.10"&gt;jquery@1.11.10&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;
&lt;a href="mailto:jquery@3.0.2"&gt;jquery@3.0.2&lt;/a&gt;!&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:tracker@1.3.2"&gt;tracker@1.3.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:tracker@1.3.4"&gt;tracker@1.3.4&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:standard-minifier-css@1.9.2"&gt;standard-minifier-css@1.9.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:standard-minifier-css@1.9.3"&gt;standard-minifier-css@1.9.3&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:standard-minifier-js@2.8.1"&gt;standard-minifier-js@2.8.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:standard-minifier-js@3.0.0"&gt;standard-minifier-js@3.0.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:es5-shim@4.8.0"&gt;es5-shim@4.8.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:es5-shim@4.8.1"&gt;es5-shim@4.8.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:ecmascript@0.16.7"&gt;ecmascript@0.16.7&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:ecmascript@0.16.10"&gt;ecmascript@0.16.10&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;momentjs:&lt;a href="mailto:moment@2.29.3"&gt;moment@2.29.3&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;momentjs:&lt;a href="mailto:moment@2.30.1"&gt;moment@2.30.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:underscore@1.0.13"&gt;underscore@1.0.13&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:underscore@1.6.4"&gt;underscore@1.6.4&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mdg:&lt;a href="mailto:validated-method@1.3.0"&gt;validated-method@1.3.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;mdg:&lt;a href="mailto:validated-method@1.3.0"&gt;validated-method@1.3.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dburles:&lt;a href="mailto:collection-helpers@2.0.0"&gt;collection-helpers@2.0.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;dburles:&lt;a href="mailto:collection-helpers@2.0.0"&gt;collection-helpers@2.0.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mdg:&lt;a href="mailto:validation-error@0.5.1"&gt;validation-error@0.5.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;mdg:&lt;a href="mailto:validation-error@0.5.1"&gt;validation-error@0.5.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:check@1.3.2"&gt;check@1.3.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:check@1.4.4"&gt;check@1.4.4&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:ddp-rate-limiter@1.2.0"&gt;ddp-rate-limiter@1.2.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:ddp-rate-limiter@1.2.2"&gt;ddp-rate-limiter@1.2.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:email@2.2.5"&gt;email@2.2.5&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:email@3.1.2"&gt;email@3.1.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:reactive-dict@1.3.1"&gt;reactive-dict@1.3.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:reactive-dict@1.3.2"&gt;reactive-dict@1.3.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dburles:&lt;a href="mailto:factory@1.5.0"&gt;factory@1.5.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;dburles:&lt;a href="mailto:factory@1.5.0"&gt;factory@1.5.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;anti:&lt;a href="mailto:fake@0.4.1"&gt;fake@0.4.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;anti:&lt;a href="mailto:fake@0.4.1"&gt;fake@0.4.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;velocity:&lt;a href="mailto:meteor-stubs@1.1.1"&gt;meteor-stubs@1.1.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;velocity:&lt;a href="mailto:meteor-stubs@1.1.1"&gt;meteor-stubs@1.1.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:random@1.2.1"&gt;random@1.2.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:random@1.2.2"&gt;random@1.2.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:shell-server@0.5.0"&gt;shell-server@0.5.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:shell-server@0.6.1"&gt;shell-server@0.6.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sacha:&lt;a href="mailto:spin@2.3.1"&gt;spin@2.3.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;sacha:&lt;a href="mailto:spin@2.3.1"&gt;spin@2.3.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:session@1.2.1"&gt;session@1.2.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:session@1.2.2"&gt;session@1.2.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:tinytest@1.2.2"&gt;tinytest@1.2.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:tinytest@1.3.1"&gt;tinytest@1.3.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:oauth2@1.3.2"&gt;oauth2@1.3.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:oauth2@1.3.3"&gt;oauth2@1.3.3&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;jparker:&lt;a href="mailto:crypto-md5@0.1.1"&gt;crypto-md5@0.1.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;jparker:&lt;a href="mailto:crypto-md5@0.1.1"&gt;crypto-md5@0.1.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:base64@1.0.12"&gt;base64@1.0.12&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:base64@1.0.13"&gt;base64@1.0.13&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:dynamic-import@0.7.3"&gt;dynamic-import@0.7.3&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:dynamic-import@0.7.4"&gt;dynamic-import@0.7.4&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:server-render@0.4.1"&gt;server-render@0.4.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:server-render@0.4.2"&gt;server-render@0.4.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:service-configuration@1.3.1"&gt;service-configuration@1.3.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:service-configuration@1.3.5"&gt;service-configuration@1.3.5&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:blaze-hot@1.1.1"&gt;blaze-hot@1.1.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:blaze-hot@2.0.0"&gt;blaze-hot@2.0.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:hot-module-replacement@0.5.3"&gt;hot-module-replacement@0.5.3&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:hot-module-replacement@0.5.4"&gt;hot-module-replacement@0.5.4&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:autoupdate@1.8.0"&gt;autoupdate@1.8.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:autoupdate@2.0.0"&gt;autoupdate@2.0.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;meteortesting:&lt;a href="mailto:mocha@2.1.0"&gt;mocha@2.1.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;meteortesting:&lt;a href="mailto:mocha@3.2.0"&gt;mocha@3.2.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:accounts-base@2.2.8"&gt;accounts-base@2.2.8&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:accounts-base@3.0.4"&gt;accounts-base@3.0.4&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:accounts-facebook@1.3.3"&gt;accounts-facebook@1.3.3&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:accounts-facebook@1.3.4"&gt;accounts-facebook@1.3.4&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:accounts-google@1.4.0"&gt;accounts-google@1.4.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:accounts-google@1.4.1"&gt;accounts-google@1.4.1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:accounts-password@2.3.4"&gt;accounts-password@2.3.4&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:accounts-password@3.0.3"&gt;accounts-password@3.0.3&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="mailto:accounts-ui@1.4.2"&gt;accounts-ui@1.4.2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:accounts-ui@1.4.3"&gt;accounts-ui@1.4.3&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tap:&lt;a href="mailto:i18n@1.8.2"&gt;i18n@1.8.2&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;tap:&lt;a href="mailto:i18n@2.0.1"&gt;i18n@2.0.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Forked - dependencies changed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;percolate:&lt;a href="mailto:momentum@0.7.2"&gt;momentum@0.7.2&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;percolate:&lt;a href="mailto:momentum@0.7.3"&gt;momentum@0.7.3&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Forked - dependencies changed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;aldeed:&lt;a href="mailto:collection2@2.10.0"&gt;collection2@2.10.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;aldeed:&lt;a href="mailto:collection2@4.0.3"&gt;collection2@4.0.3&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;quave:&lt;a href="mailto:accounts-apple@3.0.0"&gt;accounts-apple@3.0.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;quave:&lt;a href="mailto:accounts-apple@4.0.0"&gt;accounts-apple@4.0.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;aldeed:&lt;a href="mailto:autoform@5.8.1"&gt;autoform@5.8.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;aldeed:&lt;a href="mailto:autoform@8.0.0-rc.4"&gt;autoform@8.0.0-rc.4&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Required application changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;aldeed:&lt;a href="mailto:simple-schema@1.5.4"&gt;simple-schema@1.5.4&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;aldeed:&lt;a href="mailto:simple-schema@2.0.0"&gt;simple-schema@2.0.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Required extensive application changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;softwarerero:&lt;a href="mailto:accounts-t9n@2.6.0"&gt;accounts-t9n@2.6.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;New&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;useraccounts:&lt;a href="mailto:core@1.17.2"&gt;core@1.17.2&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;New&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;lmieulet:&lt;a href="mailto:meteor-coverage@5.0.0"&gt;meteor-coverage@5.0.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;New&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;johanbrook:&lt;a href="mailto:publication-collector@1.1.0"&gt;publication-collector@1.1.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;johanbrook:&lt;a href="mailto:publication-collector@1.1.0"&gt;publication-collector@1.1.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Forked - functional fix &amp;amp; dependencies changed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gwendall:&lt;a href="mailto:autoform-i18n@0.1.9_2"&gt;autoform-i18n@0.1.9_2&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;gwendall:&lt;a href="mailto:autoform-i18n@0.1.9_2"&gt;autoform-i18n@0.1.9_2&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Forked - dependencies changed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bozhao:&lt;a href="mailto:link-accounts@2.8.0"&gt;link-accounts@2.8.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;bozhao:&lt;a href="mailto:link-accounts@3.0.1"&gt;link-accounts@3.0.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tmeasday:&lt;a href="mailto:publish-counts@0.8.0"&gt;publish-counts@0.8.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;compat:&lt;a href="mailto:publish-counts@1.0.0"&gt;publish-counts@1.0.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Replaced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;splendido:&lt;a href="mailto:accounts-emails-field@1.2.0"&gt;accounts-emails-field@1.2.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;splendido:&lt;a href="mailto:accounts-emails-field@1.2.0"&gt;accounts-emails-field@1.2.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Forked - needed asyncing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cultofcoders:&lt;a href="mailto:persistent-session@0.4.5"&gt;persistent-session@0.4.5&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;itgenio:&lt;a href="mailto:persistent-session@0.4.12"&gt;persistent-session@0.4.12&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Replaced, forked - dependencies changed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rocketchat:&lt;a href="mailto:oauth2-server@2.1.0"&gt;oauth2-server@2.1.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;rocketchat:&lt;a href="mailto:oauth2-server@2.1.0"&gt;oauth2-server@2.1.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Forked - needed asyncing and dependencies changed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useraccounts:&lt;a href="mailto:bootstrap@1.14.2"&gt;bootstrap@1.14.2&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;useraccounts:&lt;a href="mailto:bootstrap@1.15.3"&gt;bootstrap@1.15.3&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reywood:&lt;a href="mailto:bootstrap3-sass@3.3.5_1"&gt;bootstrap3-sass@3.3.5_1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;reywood:&lt;a href="mailto:bootstrap3-sass@3.3.7_1"&gt;bootstrap3-sass@3.3.7_1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Forked - dependencies change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;communitypackages:&lt;a href="mailto:autoform-bootstrap3@2.0.0"&gt;autoform-bootstrap3@2.0.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;New&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;markdown1.0.12&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:markdown@2.0.0"&gt;markdown@2.0.0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Updated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;aldeed:&lt;a href="mailto:autoform-bs-datepicker@1.2.0"&gt;autoform-bs-datepicker@1.2.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;aldeed:&lt;a href="mailto:autoform-bs-datepicker@2.0.0"&gt;autoform-bs-datepicker@2.0.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Forked - dependencies changed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rajit:&lt;a href="mailto:bootstrap3-datepicker@1.7.1_1"&gt;bootstrap3-datepicker@1.7.1_1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;rajit:&lt;a href="mailto:bootstrap3-datepicker@1.7.1_1"&gt;bootstrap3-datepicker@1.7.1_1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tsega:&lt;a href="mailto:bootstrap3-datetimepicker@4.17.47"&gt;bootstrap3-datetimepicker@4.17.47&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;tsega:&lt;a href="mailto:bootstrap3-datetimepicker@4.17.47"&gt;bootstrap3-datetimepicker@4.17.47&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;kadira:flow-router&lt;/td&gt;
&lt;td&gt;ostrio:&lt;a href="mailto:flow-router-extra@3.11.0-rc300.1"&gt;flow-router-extra@3.11.0-rc300.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Forked - needed coffescript dependencies change and a functional fix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useraccounts:&lt;a href="mailto:flow-routing@2.12.1"&gt;flow-routing@2.12.1&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;useraccounts:&lt;a href="mailto:flow-routing-extra@1.1.0"&gt;flow-routing-extra@1.1.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Replaced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;kadira:&lt;a href="mailto:blaze-layout@2.3.0"&gt;blaze-layout@2.3.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;kadira:&lt;a href="mailto:blaze-layout@2.3.0"&gt;blaze-layout@2.3.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Forked - dependency change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fourseven:&lt;a href="mailto:scss@4.15.0"&gt;scss@4.15.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;fourseven:&lt;a href="mailto:scss@4.17.0-rc.0"&gt;scss@4.17.0-rc.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Needed: brew install &lt;a href="mailto:python@3.11"&gt;python@3.11&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;aldeed:&lt;a href="mailto:template-extension@4.1.0"&gt;template-extension@4.1.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;aldeed:&lt;a href="mailto:template-extension@4.1.0"&gt;template-extension@4.1.0&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Forked - dependency changed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;arillo:flow-router-helpers&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xolvio:cleaner&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hwilson:stub-collections&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;simple:reactive-method&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;autoform-markdown&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;http&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed - use fetch now&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;jkeuster:http&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed - use fetch now&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;facebook-config-ui&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;facebook-oauth&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;quave:apple-oauth&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;google-config-ui&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;meteorhacks:picker&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed - now using webapp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;practicalmeteor:chai&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;practicalmeteor:sinon&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;meteorhacks:zones&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dispatch:mocha&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fetch&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Removed - now using npm package&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Getting the app to work again
&lt;/h2&gt;

&lt;p&gt;Once I got the build working I fired up the browser to see what happened. It didn't work, of course. So I had a period of a few weeks where I was wholesale fixing and refactoring throughout the app to the point where I eventually had the app basically able to operate but still with many bugs and issues. There was much work in upgrading the client for the following reasons, though the process did involve a lot of server-side fixing now that I was using the app for real (remember the automated tests are security and sanity checks - they don't achieve real-world semantic or scenario testing):&lt;/p&gt;

&lt;h3&gt;
  
  
  aldeed:simple-schema upgrade
&lt;/h3&gt;

&lt;p&gt;I use schemas to check the data passed into my templates. I have a lot of templates - 732 of them and most of them take some kind of data. So all my template simple-schemas had to be upgraded. At the same time I took the opportunity to better standardise on this practice.&lt;/p&gt;

&lt;h4&gt;
  
  
  async functions
&lt;/h4&gt;

&lt;p&gt;Despite minimising the bubbling up of async functions having to be dealt with by the client, there's still lots of them. Sometimes they are innocuous as the new Blaze does a good job of resolving them. But other times action has to be taken. Here's two examples:&lt;/p&gt;

&lt;p&gt;If I have &lt;code&gt;{{&amp;gt; nestedTemplate data=getAsyncHelperValue}}&lt;/code&gt; in my blaze template, poor old nestedTemplate receives a promise. No good. So I'd generally change this to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{#let asyncHelperValue=getAsyncHelperValue}}
    {{#if @resolved "asyncHelperValue"}}
        {{&amp;gt; nestedTemplate data=asyncHelperValue}}
    {{/if}}
{{/let}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another issue was the loss of reactivity within an async function - so my UI did not update as expected. You lose reactivity after the first await inside an async reactive function. Often I could resolve the issue just be ensuring the reactivity that was really important was as a result of the first await in the function. But sometimes I needed reactivity based on more than one reactive source change. I then had to resort to using &lt;code&gt;Tracker.withComputation&lt;/code&gt; that restores reactivity after losing it from the first await. Truth be told, I thought this was going to be a major problem for my app. But it turns out there were relatively few instances where I had to use &lt;code&gt;Tracker.withComputation&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  method calls
&lt;/h4&gt;

&lt;p&gt;My method calls in the client would generally follow this pattern, using &lt;code&gt;mdg:validated-method&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;myMethod.call(params,(error,result) =&amp;gt; error ? showError(error) : process(result))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Often I do not need to process any result so that becomes simply&lt;br&gt;
&lt;code&gt;myMethod.call(params,showError)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;showError()&lt;/code&gt; is my ubiquitous "Oops, sorry, something went wrong" message to the user.&lt;/p&gt;

&lt;p&gt;I wanted to keep this pattern because I have 801 method calls. But I needed to use the &lt;code&gt;callAsync()&lt;/code&gt; method on &lt;code&gt;mdg:validated-method&lt;/code&gt; because all my methods were now async and that would mean changing the pattern and having to async my functions. So I implemented a new method on this class called 'callSync()' that went as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ValidatedMethod.prototype.callSync=async function(parameter,callback) {
    if (_.isFunction(parameter)) {
        callback=parameter;
        parameter=undefined;
    }
    try {
        let result=await this.callAsync(parameter);
        if (_.isFunction(callback)) callback(null,result);
    } catch (error) {
        if (_.isFunction(callback)) callback(error);
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then it was just a matter of replacing all &lt;code&gt;method.call()&lt;/code&gt; invocations into &lt;code&gt;method.callSync()&lt;/code&gt; invocations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration testing
&lt;/h2&gt;

&lt;p&gt;Having reached the point where wholesale changes seemed to be a thing of the past, I now needed to touch every part of the functional app. It's a big system. Hundreds of different screens and functionalities and combinations. I installed and built a few tests with &lt;a href="https://www.cypress.io" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;, but I soon realised that it would take me a decade to set up enough tests in cypress (with good seeded data) to make them meaningful. So I ditched that and went manual. Instead I used &lt;a href="https://dynalist.io" rel="noopener noreferrer"&gt;Dynalist&lt;/a&gt; to quickly and easily (it's very good) build a deep nested structure (using several separate files) that reflected full navigation paths throughout the app. This allowed me to at least record what needed to be tested and introduced the discipline to reach every part of the app. It was no good testing the 10% of the app that was used 90% of the time since every single bit was subject to change and risked not working. So I had to test the 90% of the app that was used only 10% of the time. Though the former did receive greater attention.&lt;/p&gt;

&lt;p&gt;The app has many points of integration to the outside world and these too needed to be included in the test plan. This included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Private API - I expose my methods and publications through a REST interface which is used externally. Mainly AWS Lambda functions as well as an AWS API implementation that exposes a limited public API to the system&lt;/li&gt;
&lt;li&gt;Social logins and management - Facebook, Google &amp;amp; Apple&lt;/li&gt;
&lt;li&gt;Integrations with Stripe, Doorflow (a security system), EposNow (a PoS system) and Mailchimp&lt;/li&gt;
&lt;li&gt;OAuth2 flows - with external systems as well as the apps own OAuth2 service.&lt;/li&gt;
&lt;li&gt;Communications to networked devices (SNMP)&lt;/li&gt;
&lt;li&gt;Webhooks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was always satisfying to find a bug that was already there from before and fixing that - I found quite a few! Who knows, the new version might have less bugs than the old by the time it goes live!&lt;/p&gt;

&lt;h2&gt;
  
  
  User acceptance testing
&lt;/h2&gt;

&lt;p&gt;This consists of two phases; Alpha and Beta. The fact that the database has not changed and that testing so far gives us confidence that the new app won't corrupt the database is a huge benefit allowing us to test the new app in a live environment. In doing so we can compare and contrast screens and behaviour between the production site and the test site at all times. There have been minimal visible changes so the screens should match precisely making it easy to spot unexpected differences in behaviour. The test version has &lt;a href="https://www.hotjar.com" rel="noopener noreferrer"&gt;hotjar&lt;/a&gt; installed making it easy for users to provide feedback and for us to track behaviour&lt;/p&gt;

&lt;h3&gt;
  
  
  Alpha testing
&lt;/h3&gt;

&lt;p&gt;I deploy the app (to Galaxy) with an alpha subdomain so that my internal team can use the new app against the production database.  This phase lasts 1 month where we can root out many of the remaining issues whilst using the system for real.&lt;/p&gt;

&lt;h3&gt;
  
  
  Beta testing
&lt;/h3&gt;

&lt;p&gt;I deploy the app with a beta subdomain and widen out its use by inviting friendly customers and users to use the new system. This phase may last 1 or 2 months, depending on how it goes, for further opportunities to find bugs while the system is used by people of different roles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rollout and re-issue of iOS &amp;amp; Android apps
&lt;/h2&gt;

&lt;p&gt;This is the final stage of the project. The production domain is upgraded to the new app at the same time as we deploy compatible new versions of the iOS and Android apps. It's normally a bit of a battle to get the apps building, sadly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;At first the task seemed daunting. But even then I'm not sure I realised just how much work was involved. But as with any project, it was a matter of breaking it down and building lists of what had to be done in an orderly fashion. And then tracking progress on each task and seeing that progress slowly reach 100% complete. Take the unit tests for the meteor methods for example. There are 519 of them. Every one needed a test. Some days I'd get dozens done. Other days only a few. But sooner or later I knew that 100% would arrive! We are now in a much better place, technologically, than before and this upgrade has forced us to use where possible all the latest packages and components as well as having established reasonably comprehensive test harnesses and procedures.&lt;/p&gt;

&lt;p&gt;While it's been a lot of work for me, I know it's been many times more for others without whose work this could not have been achieved. So thanks as ever to the Meteor team and the community for making it possible!&lt;/p&gt;

&lt;p&gt;I now look forward to many more years of happy Meteoring.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>meteor</category>
    </item>
    <item>
      <title>How We Scaled Meteor to Handle 30,000 Concurrent Users at Propiedata</title>
      <dc:creator>Paulo Mogollon</dc:creator>
      <pubDate>Mon, 24 Feb 2025 18:24:43 +0000</pubDate>
      <link>https://forem.com/meteor/how-we-scaled-meteor-to-handle-30000-concurrent-users-at-propiedata-2aaa</link>
      <guid>https://forem.com/meteor/how-we-scaled-meteor-to-handle-30000-concurrent-users-at-propiedata-2aaa</guid>
      <description>&lt;p&gt;Scaling Meteor is both an art and a science.&lt;/p&gt;

&lt;p&gt;At Propiedata, a property management platform with features like virtual assemblies, dashboards, and real-time voting, chat, reactions and participation queues, we successfully scaled our app to handle &lt;strong&gt;peaks of 30,000 concurrent users.&lt;/strong&gt; Here's how we did it and the lessons learned along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Favor Methods Over Publications
&lt;/h2&gt;

&lt;p&gt;Meteor's publications can be expensive in terms of server and database resources. While powerful, they aren't always necessary for all types of data. Switching to methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduces load on your servers.&lt;/li&gt;
&lt;li&gt;Improves response times.&lt;/li&gt;
&lt;li&gt;Performance is more stable and dependable.&lt;/li&gt;
&lt;li&gt;Optimizes performance for complex queries.&lt;/li&gt;
&lt;li&gt;Methods can be easily cached.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What did we fetch with methods?
&lt;/h2&gt;

&lt;p&gt;Everything! We just subscribed to data that required real-time information like poll results, chats, assembly state and participation queues.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Optimize MongoDB Schemas and Queries
&lt;/h2&gt;

&lt;p&gt;Efficient database queries are the backbone of scaling any app.&lt;br&gt;
Here's what worked for us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Indexes: Use compound indexes tailored to how your data is queried.&lt;/li&gt;
&lt;li&gt;Selective Fields: Only retrieve the fields you need.&lt;/li&gt;
&lt;li&gt;Avoid Regex: Regex queries can be a performance killer.&lt;/li&gt;
&lt;li&gt;Secondary Reads: Offload read operations to secondary replicas when possible.&lt;/li&gt;
&lt;li&gt;Monitor Performance: Regularly check for long-running queries and eliminate n+1 issues.&lt;/li&gt;
&lt;li&gt;Too Many Indexes: Having too many indexes can hurt your write performance.&lt;/li&gt;
&lt;li&gt;ESR Rule: When creating an index the Equality fields go first, then Sort and at last Range, we will go deeper later.&lt;/li&gt;
&lt;li&gt;MF3 rule: Most filtering field first, which means that in any query filter, a field that filters more should goes first.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Move Heavy Jobs Out of the Main App
&lt;/h2&gt;

&lt;p&gt;Offloading resource-intensive tasks from the main (user facing) application reduces server load and improves the responsiveness of methods and subscriptions. Using external job queues or microservices ensures more stable and dependable performance, especially during peak times.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what we moved off from the main app?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Bulk imports&lt;/li&gt;
&lt;li&gt;Analytics aggregations&lt;/li&gt;
&lt;li&gt;Real time data aggregations&lt;/li&gt;
&lt;li&gt;PDF/HTML rendering&lt;/li&gt;
&lt;li&gt;Batch data cleansing&lt;/li&gt;
&lt;li&gt;Batch email sending&lt;/li&gt;
&lt;li&gt;Puppeteer page crawling&lt;/li&gt;
&lt;li&gt;Large data reads and documents creation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Implement Redis Oplog
&lt;/h2&gt;

&lt;p&gt;Switching to Redis Oplog was a game-changer. It significantly reduced server load by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Listening to specific changes through channels.&lt;/li&gt;
&lt;li&gt;Publishing only the necessary changes. This approach minimized the overhead caused by Meteor's default oplog tailing.&lt;/li&gt;
&lt;li&gt;Debounce requerying when processing bulk payloads.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Cache Frequently Used Data
&lt;/h2&gt;

&lt;p&gt;Caching common queries or computationally expensive results dramatically reduces database calls and response times. This is particularly useful for read-heavy applications with repetitive queries.&lt;/p&gt;

&lt;p&gt;We used Grapher so that made it easy to cache data in redis or memory.&lt;/p&gt;

&lt;p&gt;Don't make the same error we did at first caching also the firewall or security section of the method calls (we did this before using Grapher).&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Follow General MongoDB Principles
&lt;/h2&gt;

&lt;p&gt;To get the most out of MongoDB:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always use compound indexes.&lt;/li&gt;
&lt;li&gt;Ensure every query has an index and every index is used by a query.&lt;/li&gt;
&lt;li&gt;Filter and limit queries as much as possible.&lt;/li&gt;
&lt;li&gt;Follow the Equality, Sort, Range (ESR) rule when creating indexes.&lt;/li&gt;
&lt;li&gt;Prioritize the field that filters the most for the first index position.&lt;/li&gt;
&lt;li&gt;Use TTL indexes to expire your old data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is the ESR rule?
&lt;/h2&gt;

&lt;p&gt;The ESR Rule is a guideline for designing efficient indexes to optimize query performance. It stands for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Equality: Fields used for exact matches (e.g., { x: 1 }) should come first in the index. These are the most selective filters and significantly narrow down the dataset early in the query process.&lt;/li&gt;
&lt;li&gt;Sort: Fields used for sorting the results (e.g., { createdAt: -1 }) should be next in the index. This helps MongoDB avoid sorting the data in memory, which can be resource-intensive.&lt;/li&gt;
&lt;li&gt;Range: Fields used for range queries (e.g., { $gte: 1 }) should come last in the index, as they scan broader parts of the dataset.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is the MF3 rule?
&lt;/h2&gt;

&lt;p&gt;Well, I just named it that way at the moment of writing, but this rule prioritizes fields that filter the dataset the most at the beginning of the index. Think of it as a pipeline: the more each field filters the dataset in each step, the fewer resources the query uses in the less performant parts, like range filters. By placing the most selective fields first, you optimize the query process and reduce the workload for MongoDB, especially in more resource-intensive operations like range queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Secure Your MongoDB Cluster
&lt;/h2&gt;

&lt;p&gt;A critical step in scaling securely is ensuring your database is not exposed to the internet. Initially, we relied on a strong, hard-to-guess username and password for security. However, we discovered that much of our resource usage was caused by automated scripts attempting to connect to our database.&lt;/p&gt;

&lt;p&gt;Even unsuccessful login attempts consume server resources due to hashing and cryptographic operations. When multiplied by thousands of attempts from bots or malicious scripts, this can significantly impact performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up VPC peering: This allows your database to communicate securely with your application servers without exposing it to the public internet.&lt;/li&gt;
&lt;li&gt;Use IP Access Lists: If you're hosting your database on platforms like MongoDB Atlas, restrict access to known IPs only.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By implementing these measures, you prevent unnecessary resource usage from brute-force attempts and enhance the overall security and performance of your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Other Key Improvements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Rate Limiting: Prevent abuse of your methods by implementing rate limits.&lt;/li&gt;
&lt;li&gt;Collection Hooks: Be cautious with queries triggered by collection hooks or other packages.&lt;/li&gt;
&lt;li&gt;Package Evaluation: Not every package will perfectly fit your needs - adjust or create your own solutions when necessary.&lt;/li&gt;
&lt;li&gt;Aggregate Data Once: Pre-compute and save aggregated data to avoid repetitive calculations and queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. The Result: Performance and Cost Efficiency
&lt;/h2&gt;

&lt;p&gt;These optimizations led to tangible results:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cost Reduction: Monthly savings of $2,000.&lt;/li&gt;
&lt;li&gt;Peak Capacity: Serving 30,000 peak concurrent users for just $1,000/month.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Recap
&lt;/h2&gt;

&lt;p&gt;If you're looking to scale your Meteor application, here are the key takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Offload heavy jobs to external processes.&lt;/li&gt;
&lt;li&gt;Use methods instead of publications where possible.&lt;/li&gt;
&lt;li&gt;Optimize MongoDB queries with compound indexes and smart schema design.&lt;/li&gt;
&lt;li&gt;Leverage Redis Oplog to minimize oplog tailing overhead.&lt;/li&gt;
&lt;li&gt;Cache data to speed up responses.&lt;/li&gt;
&lt;li&gt;Think "MongoDB," not "Relational."&lt;/li&gt;
&lt;li&gt;Secure your cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Almost forgot
&lt;/h2&gt;

&lt;p&gt;We use AWS EBS to deploy our servers, with 4Gb memory and 2vCPUs. It's configured to autoscale, having in mind that NodeJS uses only one vCPU, memory is almost always at 1.5gb. And for MongoDB we use Atlas, this also auto scales but it has an issue, autoscaling takes about an hour to scale up when it has a heavy load, so we created a system that predicts usage given the amount of assemblies we have and scales Mongo cluster accordingly for that period.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Meteor 3.1.1 is here!</title>
      <dc:creator>Gabs Ferreira</dc:creator>
      <pubDate>Tue, 04 Feb 2025 16:18:27 +0000</pubDate>
      <link>https://forem.com/meteor/meteor-311-is-here-1meo</link>
      <guid>https://forem.com/meteor/meteor-311-is-here-1meo</guid>
      <description>&lt;p&gt;Meteor 3.1.1 is here! This latest patch brings performance improvements, critical fixes, and updates based on community feedback. &lt;/p&gt;

&lt;p&gt;You can check out all that's new about his version in this video, where I had a chat with the core team:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/tZY6jZGU9Ok"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Or just keep reading :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance improvements: faster real-time processing
&lt;/h2&gt;

&lt;p&gt;One of the highlights of Meteor 3.1.1 is a boost in real-time performance. Our team refactored the synchronous queue for parallel processing and optimized MongoDB observers to handle initial documents more efficiently.&lt;/p&gt;

&lt;p&gt;Previously, Meteor 3.1 had some performance regressions when dealing with reactive flows, limiting the number of connections it could handle. This patch resolves those issues and improves Meteor 3's scalability, outperforming previous Meteor 2 versions in terms of handling more simultaneous connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deprecation of Async Allow/Deny Rules
&lt;/h2&gt;

&lt;p&gt;Based on community feedback, async rules have been deprecated, and the API has been streamlined to focus on just insert, update, and remove operations. Additionally, test coverage has been expanded to address edge cases identified by developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Meteor.deprecate
&lt;/h2&gt;

&lt;p&gt;Meteor now includes a &lt;em&gt;Meteor.deprecate&lt;/em&gt; API, which was initially designed for internal use but is now accessible to library developers. This feature allows more precise tracking of deprecated functions and API calls, helping developers transition smoothly when changes occur. Although it's not yet fully documented, advanced users can explore it in the Meteor source code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Node.js Upgrade and Community Fixes
&lt;/h2&gt;

&lt;p&gt;This version also includes an upgrade to the latest Node.js version, along with multiple community-driven fixes. The team has addressed several GitHub issues, improved the Accounts package, and implemented security updates. It also introduces fixes for Windows users, ensuring a more stable development environment across platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meteor RPC: A New Approach to API Calls
&lt;/h2&gt;

&lt;p&gt;A significant addition to the Meteor ecosystem is the release of Meteor RPC, launched in December, a new package designed to streamline remote procedure calls (RPC) and enhance real-time capabilities. &lt;/p&gt;

&lt;p&gt;This package, powered by Zod for runtime validation, brings improved TypeScript support and a more modern approach to defining and calling APIs in Meteor. It's already powering &lt;a href="https://www.meteor.com/cloud" rel="noopener noreferrer"&gt;Galaxy&lt;/a&gt;, meaning if you're a Galaxy user, you're already benefiting from it!&lt;/p&gt;

&lt;p&gt;If you want to explore Meteor RPC, check out the &lt;a href="https://blog.meteor.com/introducing-the-grubba-rpc-package-80b1e1958dc3" rel="noopener noreferrer"&gt;official blog post&lt;/a&gt; or join the conversation &lt;a href="https://discord.com/invite/3w7EKdpghq" rel="noopener noreferrer"&gt;on Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>meteor</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>How to Migrate your MongoDB Database to Galaxy Hosting</title>
      <dc:creator>David Amaral</dc:creator>
      <pubDate>Fri, 17 Jan 2025 12:53:22 +0000</pubDate>
      <link>https://forem.com/meteor/how-to-migrate-your-mongodb-database-to-galaxy-mongodb-hosting-54kn</link>
      <guid>https://forem.com/meteor/how-to-migrate-your-mongodb-database-to-galaxy-mongodb-hosting-54kn</guid>
      <description>&lt;p&gt;Migrating a database can be quite a challenge, right?&lt;/p&gt;

&lt;p&gt;At Galaxy, we truly understand how stressful technical tasks can be and are here to make things easier for you. Hence, we created this follow-up article to facilitate your first MongoDB database migration to our Galaxy cloud. These steps are recommended for databases up to &lt;strong&gt;15GB in size and unsuitable for MongoDB clusters in sharded mode.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please note that this procedure &lt;strong&gt;will have downtime&lt;/strong&gt;. If you need to migrate a larger database or complex structure without downtime, please contact our specialists via our support chat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get your environment ready!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To complete this tutorial, we only need Docker, as it runs the container for all migration steps installed. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Set Up Docker
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why Docker?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Docker simplifies migrations by running pre-configured containers, avoiding manual installations and dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install Docker:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Download and install Docker from &lt;a href="//docker.com"&gt;Docker&lt;/a&gt;. It’s quick and supports all major operating systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Prepare Database Details
&lt;/h2&gt;

&lt;p&gt;Make sure you have your connection strings from your source and destination databases. This example shows a connection string for Galaxy hosting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mongodb://admin:passwordEncodedb@user_testcluster-01.mongodb.galaxy-cloud.io:30010,user_testcluster-02.mongodb.galaxy-cloud.io:30010,user_testcluster-03.mongodb.galaxy-cloud.io:30010/admin?replicaSet=test_replicaset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Stop your application
&lt;/h2&gt;

&lt;p&gt;We don't want inconsistent data, right? &lt;br&gt;
So, at this step, we need to stop our application so that it does not write any data to our database. After a complete stop, we can proceed with the migration.&lt;/p&gt;

&lt;p&gt;When ready, start the migration process by executing the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm –name mongo-migration-tool -d \
  -e SOURCE_URI="" \
  -e TARGET_URI="" \
  -e DB_NAME="example_db_name" \
  meteor/galaxy-mongodb-migrate:202409101534
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start a container that will dump the source database and restore this dump in the destination database.&lt;/p&gt;

&lt;p&gt;You can verify if the container is running by executing the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# docker ps | grep mongo-migration-tool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, you can verify the backup progress by examining the logs of this container with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# docker logs mongo-migration-tool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Verify and Secure
&lt;/h2&gt;

&lt;p&gt;After it is complete, the container is stopped and removed. You can now see all the data on your destination database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspect the Data:
&lt;/h3&gt;

&lt;p&gt;Use tools like MongoDB Compass to confirm successful migration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create New Users:
&lt;/h3&gt;

&lt;p&gt;Enhance security by creating dedicated database users in Galaxy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations and Recommendations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Database Size:&lt;/strong&gt; For databases over 15GB, alternative methods may be more effective.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sharded Mode:&lt;/strong&gt; This process does not support sharded MongoDB configurations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Configure your application to your new connection string
&lt;/h2&gt;

&lt;p&gt;After a successful migration, you can change your app's configuration and restart it to use the data in your database located on our Galaxy MongoDB hosting. &lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Migrating your MongoDB database to Galaxy Hosting is an essential step in leveraging the full potential of our reliable and scalable cloud platform.&lt;/p&gt;

&lt;p&gt;Remember, this guide is tailored for databases up to 15GB and non-sharded configurations. If your requirements fall outside these parameters or you prefer a migration with no downtime, don’t hesitate to contact our support team using the chat button on your Galaxy account. We’re here to assist you every step of the way. Also, you can review the official &lt;a href="https://galaxy-support.meteor.com/en/article/mongodb-simplify-migration-to-galaxy-database-im4qyd/" rel="noopener noreferrer"&gt;Galaxy documentation&lt;/a&gt; for more information.&lt;/p&gt;

&lt;p&gt;If you haven't created a Galaxy account yet, now's the perfect time to do so and you can test it out with a free plan! It allows you to effortlessly host a variety of applications, including Node and Meteor, with even more options coming soon. Don't miss out on this opportunity, &lt;strong&gt;&lt;a href="https://cloud.meteor.com/?isSignUp=true" rel="noopener noreferrer"&gt;create your account now&lt;/a&gt;&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Happy migrating!&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>galaxycloud</category>
      <category>database</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
