This post is part one of a two-part series brought to you by DY Labs, an initiative by members of our Product and R&D departments who have a passion for experimentation and building developer resources for the greater digital marketing and engineering communities. This series focuses on the cohort’s latest project, Funnel Rocket, which is a serverless query engine optimized for complex user-centric queries at scale. In part one, Elad Rosenheim, our VP of Technology, walks through his journey in the world of product and engineering and how his experiences in the field have pushed him and others to innovate and tackle challenges facing developers across industries in order to develop open-source solutions.
An earlier version of this post was previously published by Elad on Medium.
Over the last decade, we’ve experienced the rise and rise of open-source software for big data and big scale. That was indeed a big leap forward, yet I’ve become disillusioned with much of the surrounding hype. Rants aside, here’s where I think the underlying issues are, and most importantly – what we can do about it. It’s my personal take, so let’s start with my own personal story.
From the dot-com bubble to the open-source era
I can trace my first real job back to around 1998. During that period, real servers were still made by companies like Sun, running Solaris on expensive proprietary metal. I recall catching a glimpse of a purchase order for a few Sun Ultra workstations to roughly around 2000. One line item, in particular, caught my eyes, as I could directly compare it to my PC at home: a cool $150 for a CD drive, worth about $230 today. It’s very probable that this drive came in Sun’s iconic purple, thus exuding its commanding authority over the pedestrian CD drive in your home, but still — it didn’t feel right. Savvy young developers started pushing for Linux, and people rushed to join the first wave of the dot-com bubble.
Fast forward to 2013, when I joined a tiny startup – Dynamic Yield – and started working on “web-scale” problems in earnest. Up to that point, scale (to me) usually meant tuning a beastly Java application server doing maybe 100 requests per second at most, each request typically hitting the relational database a dozen times within a transaction. Every single request used to mean something important that someone cared about. Now, data has become a clickstream from across the web: hardly transaction-worthy, but coming in at thousands of requests per second, and growing fast.
The founding team already had their first database (a single MySQL instance) brought to its knees on that traffic and moved on to Apache HBase for anything non-administrative. Before a year went by, I introduced Redis for fast access to user data and Elasticsearch for ad-hoc analytics to our growing spiderweb of an architecture. We were deep in NoSQL territory now. For batch jobs, custom Java processes and clunky Hadoop MapReduce jobs started making way for the new shiny tech of the day: Apache Spark. Kafka and stream processing frameworks would come next.
Much of that new wealth of tools for scale was directly inspired by Google’s whitepapers. These marked a big shift in how scale and resilience were tackled or at least thought about.
First, it was about GFS (the Google File System) and MapReduce, then BigTable. It pushed the wider tech community to think in terms of commodity hardware and inexpensive hard disks rather than purple hardware and RAID, relying on multiple replicas for high availability and distributing work. You realized hardware will fail and keep failing, and what you needed were tools that will happily skip over such road bumps with minimal fuss and grow in capacity as fast as you can throw new machines at ’em.
Not having to pay a hefty per-server license fee was a big plus. The concept of GFS inspired Apache HDFS, Google MapReduce’s principles were recast as Apache Hadoop M/R, and BigTable was remade as Apache HBase. Later on, Google’s Dremel (which you probably know today in its SaaS incarnation — BigQuery) inspired the Parquet file format and a new generation of distributed query engines.
To me, these were exciting times – being able to scale so much with open source, provisioning new servers in hours or minutes! The promises of elasticity, cost efficiency, and high availability were, to a large extent, realized — especially if you had been accustomed to waiting months for servers, for IT priests to install a pricey NAS, or for the procurement of more commercial middleware licenses.
I guess this goes against the grain of nostalgia permeating so much of the discourse. Usually, it sounds something like, ���We did so much in the old days with so little memory and no-nonsense, hand-polished code! Oh, these kids and their multi-megabyte JS bundles will never know…” I like to compare that to a tip I’ve learned from parenting: There is always someone who has achieved so much more with far less but is simply eager to tell you all about it.
The burden of complexity
It seems like you only get a look at the real, gnarly underbelly of a cluster at the worst times: during peak traffic periods, at nights, or on holidays.
There is a complexity to a cluster’s state management that just does not go away, and instead, is waiting to explode at some point. Here’s how it usually starts off, at least in my experience:
- Whether you’re managing a random-access database cluster, a batch processing, or a stream processing cluster, you get it to work initially and for a while, it seems to work!
- You don’t really need to know how it elects a master, how it allocates and deallocates shards, how precious metadata is kept in sync, or what ZooKeeper actually does in there.
At some point, you hit some unexpected threshold that’s really hard to predict because it’s related to your usage patterns, your specific load spikes, and things go awry. Sometimes, the system gets completely stuck, sometimes limping along and crying out loud in the log files. Often, it’s not a question of data size or volume as you might expect, but a more obscure limit being crossed. Your Elasticsearch cluster might be fine with 2,382 indices, but one day, you get to 2,407 and nodes start breaking, pulling the rest of them down with them to misery lane. I just made up these numbers —your metrics and thresholds are likely different, but you get the picture.
In the best-case scenario, you solve the issue at hand that day, but often, the same issue will repeat. This is where you need to step back and give it time. Sometimes, it takes weeks to stabilize things or even months to hunt down a recurring issue. And over time, this becomes a time suck. Sometimes, multiple and seemingly unrelated incidents happen to all blow up over a short period of time, and the team experiences fatigue from fighting multiple fires simultaneously. Eventually, you’ve put enough work hours and thrown enough extra resources at the problem (i.e. supplying a few more servers, giving it more headroom) and it goes away, but deep down, you know it will return. As a head of R&D, I know this can be extremely draining, because whether the fire is at team A, B, or C — it’s ultimately your fire as well, every single time.
Sometimes, people will respond to your troubles with how great and reliable their tooling is or was at company X: “We’re using this awesome database Y and have never had any significant issue!” or “You’re over-complicating it, just use Z like us and your problems will go away.” However, this can often be over-simplifying the core issue at hand, skirting around the real complexity and nuances of your end goal. And over time, I’ve found solace in focusing on tending to my roots, because choosing to neglect them is only sustainable for so long.
Let’s talk about elasticity
Operational complexity is an enduring burden, but I should also mention limited elasticity and its friend, high cost. While tools do get better in that respect, what may have been considered “elastic” in 2012 is simply not what I’d call elastic today.
Let’s take Apache Spark for example. There’s still a steady stream of people going into Big Data who think it will solve all their problems, but if you’ve spent significant time with it, you know that in order for your jobs to work well, you need to carefully adjust the amount of RAM vs. CPU used, you need to dive into config settings, and perhaps even tinker with Garbage Collection a bit. You need to analyze the “naive” DAG it generates for your code to find choke points, then modify the code so it’s less about the cleanest functional abstraction and more about actual efficiency. In our case, we also needed to override some classes. And that’s how this song goes: care-free big data processing by high-level abstractions rarely lives up to the hype.
The challenge goes further, however.
One idea that Apache Hadoop pushed for since its inception was the ability to build a nice big cluster of commodity servers in order to throw several jobs from different teams at different times at its resource manager (nowadays known as YARN), letting it figure out which resources each job needs and how to fit all these jobs nicely. The concept was to think about the capacity of the cluster as an aggregate of its resources: this much CPU, storage, memory. You would scale that out as necessary, while R&D teams kept churning out new jobs to submit. That idea pretty much made its way into Spark as well.
The problem is, one single cluster really doesn’t like juggling multiple jobs with very different needs in terms of computing, memory, and storage. What you get instead is a constant battle for resources, delays, and occasional failures. Your cluster will typically be in one of two modes:
- Over-provisioned to have room for extra work (read: idle resources that you pay for), or
- Under-provisioned, leaving you wishing it was easy or quick to scale depending on how well jobs progress right at this moment (I’m not saying it’s not possible, but it’s definitely not easy, quick or out-of-the-box)
Web servers usually “have one job” and give you the ability to measure their maximum capacity as X requests per second. They rely on databases and backend servers, but they don’t need to know each other, let alone pass huge chunks of data between them over the network or thrash the disks. Data processing clusters do all these different things, concurrently, and never exactly at the same exact moment, which may cause issues. If you run into such problems, you’ll probably start managing multiple clusters, each configured to its needs and with its own headroom. However, provisioning these multiple clusters takes precious time, and operating them is still a hassle. Even a single job in isolation has multiple stages which stress different resource types (CPU, memory, disk, network), which makes optimal resource planning a challenge, even with multiple dedicated clusters.
You could get some of that work off your shoulders if you go for a managed service, but the “management tax” can easily cost outlandish amounts of money as you scale. If you’re already paying, say, $1 million a year for self-managed resources on the cloud, you have to ask yourself: Are we willing to pay 1.5x-2x that price tag to receive a managed-to-an-extent service?
New technologies (e.g. k8s operators) do provide us with faster provisioning and better resource utilization. There is one thing they cannot solve for, however: precious engineering time spent to thoroughly profile and tune misbehaving components, which in turn makes it very tempting to throw ever more compute resources at the problem. Over time, these inefficiencies accumulate, and as the organization grows, you’ll rack up a pretty significant bill to manage the entire system without an efficient solution.
Gradual improvements over time
Once your Spark cluster is properly set-up and running well, it can output huge amounts of data quickly when it reaches the result-writing stage. If the cluster is running multiple jobs, these writes come in periodic bursts.
Now, assume you want these results written into external systems, e.g. SQL databases, Redis, Elasticsearch, Cassandra. It’s all too easy for Spark to overwhelm or significantly impair any database with these big writes – I’ve even seen it break a cluster’s internal replication, which is a nightmare scenario.
You can’t really expect Elasticsearch to grow from, say, 200 cores to 1,000 for exactly the duration where you need to index things in bulk, then shrink back to 200 immediately afterwards. Instead, there are various things you can do:
- Aggressively throttle down the output from Spark — i.e. spend money being near-idle on the Spark side
- Write and manage a different component to read Spark’s output and perform the indexing (meaning dev time and operations)
- Over-provision Elasticsearch (= more money)
In other words, not really the elasticity I was hoping for.
Over time, patterns have evolved to alleviate some of these pain: Apache Kafka is frequently used as the “great decoupler”, allowing multiple receiving ends to consume data at their own pace, go down for maintenance, etc. Kafka, though, is another expensive piece of the puzzle that is definitely not as easy to scale or as resilient as the initial hype had me believing.
On the storage front, there have been improvements as well: instead of using HDFS, we switched to S3 for all batch outputs so we don’t need to worry about HDD size or filesystem metadata processes. That means giving up on the once-touted idea of “data locality” which, in hindsight, was a big mismatch. Storage size tends to go only one way: up. At the same time, you want the compute to be as elastic as possible, utilizing as much or as little as you need right now. Marrying both was always quite clumsy, but fortunately, AWS got its act together over time, improved intra-datacenter network performance considerably, and finally sorted out strong consistency in S3 (oh, the pain, the workarounds!). That brought it in line with Google Cloud on these points, making the storage-compute decoupling viable on AWS as well.
That last note is important: the building blocks offered by a cloud provider may encourage a good architecture (or push you away from one).
Don’t forget to create a dev wishlist
This isn’t an article in the style of “Stop using X, just use Y.” I believe you can create a wildly successful product (or fail spectacularly) with any popular technology. The question I tend to focus on instead is: “What constructs do we need to make systems easier, faster, and cheaper?” Here’s my partial wishlist:
- I want to launch jobs with better isolation from each other – each getting the resources it needs to run unhindered, rather than needing to fight over resources from a very limited pool, avoiding any possible domino effect from a single job derailing.
- I want the needed resources to be (nearly) instantly available
- I only want to pay for the actual work done, from the millisecond my actual code started running to the millisecond it ended.
- I want to push the complexity of orchestrating hardware and software to battle-tested components whose focus is exactly that rather than any applicative logic. Using these lower-level constructs, I could build higher-level orchestration that is way more straightforward. Simple (rather than easy) is robust.
- I want jobs to run in multiple modes: it could be “serverless” for fast, easy scaling of bursty short-lived work and interactive user requests at the expense of a higher price per compute unit/second. Or, it could be utilizing spot / preemptive instances — somewhat slower to launch and scale, but very cheap for scheduled bulk workloads.
I’m not inventing any new concepts here. The building blocks are essentially readily available these days. The open-source software to take advantage of all these to the max, however, is not so available. To demonstrate what I mean, let’s tackle a real challenge guided by these principles. In part two of this series, I will dive into Funnel Rocket, an open-source query engine that is my attempt at building a solution. The goal was to build something to solve a very specific pain point we needed to address here, at Dynamic Yield, but over time, as we’ve spent more time working on it, I’ve come to realize how it can also become a testbed for so much more. So now, let’s move on to part two.
<!DOCTYPE html> <!--[if IE 6]><html id="ie6" lang="en-US"> <![endif]--> <!--[if IE 7]><html id="ie7" lang="en-US"> <![endif]--> <!--[if IE 8]><html id="ie8" lang="en-US"> <![endif]--> <!--[if !(IE 6) | !(IE 7) | !(IE 8) ]><!--><html lang="en-US"> <!--<![endif]--><head><meta name="msvalidate.01" content="1033997EC383621B874EB0392F261984"/><link rel="preconnect" href="//cdn.dynamicyield.com"><link rel="preconnect" href="//st.dynamicyield.com"><link rel="preconnect" href="//rcom.dynamicyield.com"><link rel="dns-prefetch" href="//cdn.dynamicyield.com"><link rel="dns-prefetch" href="//st.dynamicyield.com"><link rel="dns-prefetch" href="//rcom.dynamicyield.com"> <script data-cfasync="false">window.dataLayer = window.dataLayer || [];
window.gtag = function() { dataLayer.push(arguments); }
window.gtag('consent', 'default', {
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied',
analytics_storage: 'denied',
functionality_storage: 'denied',
personalization_storage: 'denied',
security_storage: 'granted', // Only this is granted by default
});</script> <script data-cfasync="false">(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-MCQHF8');</script> <script data-cfasync="false" async>// Init the adobeDataLayer array
var adobeDataLayer = adobeDataLayer || [];
// Only when the API is ready
function adobeWaitForDY() {
if (typeof(window.DY) !== 'undefined' && typeof(window.DY.AdDetection) !== 'undefined' &&
typeof($dy) !== 'undefined' && typeof($dy(window)) !== 'undefined' && typeof($dy.renderSmartTagSlider) !== 'undefined') {
var zi_data = localStorage.getItem('ZoomInfoData'),
ada_page_info = {
"pageName": "Going for gold: The building blocks of effective open-source software ",
"siteName": "Mastercard Dynamic Yield",
"pageTitle": "en_US :dy-labs-building-blocks-open-source",
"pageURL": "https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/",
"country": "US",
"language": "en",
"dyID": DY.dyid,
"userStatus": "Guest"
};
// Detect the hierarchy and
// site sections based on the URL slugs
var current_pathname = window.location.pathname.replace(/^\/|\/$/g, '');
if(current_pathname) {
var current_sitesections = current_pathname.split('/'),
current_hierarchy = current_sitesections.map(function(segment) {
return segment.split(/[-_]/).map(function(word) {
return word.charAt(0).toUpperCase() + word.slice(1);
})
.join(' ');
});
// Site section 1
if(current_sitesections[0]) {
ada_page_info.siteSection1 = current_sitesections[0];
}
// Site section 2
if(current_sitesections[1]) {
ada_page_info.siteSection2 = current_sitesections[1];
}
// Hierarchy
ada_page_info.hierarchy = current_hierarchy.join('|');
}
// Push the ZI params as well
if(zi_data) {
zi_data = JSON.parse(zi_data);
if(zi_data.name) {
ada_page_info.ziCompany = zi_data.name;
}
if(zi_data.domain) {
ada_page_info.ziDomain = zi_data.domain;
}
if(zi_data.employeesrange) {
ada_page_info.ziEmployees = zi_data.employeesrange;
}
if(zi_data.industry) {
ada_page_info.ziIndustry = zi_data.industry;
}
}
// Decode HTML prior to dispatching the event
Object.keys(ada_page_info).forEach(function(key) {
ada_page_info[key] = $('<textarea/>').html(ada_page_info[key]).text();
});
adobeDataLayer.push({
"event": "pageLoad",
"pageInfo": ada_page_info
});
} else {
setTimeout(adobeWaitForDY, 150);
}
}
adobeWaitForDY();</script> <script type="text/javascript">function OptanonWrapper() {
console.log('OneTrust Loaded');
DY_API_update_consent_mode();
OneTrust.OnConsentChanged(DY_API_update_consent_mode);
}
function DY_API_update_consent_mode() {
var groups = OnetrustActiveGroups.split(',');
DY.userActiveConsent = {accepted: groups.includes('C0004')};
DYO.ActiveConsent.updateConsentAcceptedStatus(groups.includes('C0004'));
if(groups.includes('C0004')) {
console.log('OneTrust_Consent_Is_Granted');
DY.API('event',{ name: 'OneTrust_Consent_Is_Granted', properties: {}});
}
console.log('OneTrust - DY API is ' + (groups.includes('C0004') ? 'Enabled' : 'Disabled'));
}
window.addEventListener('OTConsentApplied', function() {
var groups = OnetrustActiveGroups.split(',');
if(groups.includes('C0004')) {
console.log('OneTrust_Initial_Consent_Granted');
DY.API('event',{ name: 'OneTrust_Initial_Consent_Granted', properties: {}});
}
});</script> <script type="text/javascript">/*WebFontConfig = {
google: { families: [ 'Shadows+Into+Light::latin', 'Handlee::latin', 'Roboto:400,100,300,500:latin' ] }
};
(function() {
var wf = document.createElement('script');
wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
'://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
wf.type = 'text/javascript';
wf.async = 'true';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(wf, s);
})(); */
console.log(
'%cLet’s personalize experiences together.\n%cDynamic Yield is hiring smart engineers like you to help solve hard problems.\n%cSee our jobs page: https://www.dynamicyield.com/careers',
'font-size:2.2em;line-height:1.4em;margin-top:20px;color:rgb(93, 56, 185);',
'font-size:1.1em;line-height:1.6em;color:rgb(0, 0, 0);',
'font-size:1.1em;line-height:1.6em;margin-bottom:20px;color:rgb(0, 0, 0);'
);
function waitForElementToDisplay(selector, time, functionName) {
if (document.getElementById(selector) != null) {
functionName();
return;
} else {
setTimeout(function () {
waitForElementToDisplay(selector, time, functionName);
}, time);
}
}
function dcWaitForJQuery(time, functionName) {
if (window.jQuery || window.n2) {
functionName();
return;
} else {
setTimeout(function () {
dcWaitForJQuery(time, functionName);
}, time);
}
}</script> <meta name="msvalidate.01" content="451B75B70520F4C76D67F116C9EFFE5C"/><meta property="twitter:account_id" content="4503599629852947"/><meta name="p:domain_verify" content="f8112f57c09778e892850075a87dc1cf"/><meta name="google-site-verification" content="9FbmfdC4cM7JG8sgYh6w9HhFlxvEHewltexeUVzuSfE"/><meta charset="UTF-8"/><link rel="pingback" href="https://www.dynamicyield.com/xmlrpc.php"/> <!--[if lt IE 9]> <script src="https://www.dynamicyield.com/wp-content/themes/Divi/js/html5.js" type="text/javascript"></script> <![endif]--> <script type="text/javascript">document.documentElement.className = 'js';</script> <script type="text/javascript">var getLangCode = 'en';</script> <link rel="prefetch" href="/wp-content/themes/Divi/css/custom-style.css" as="style" crossorigin="anonymous"><meta name='robots' content='index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1' /><link rel="alternate" hreflang="en" href="https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/" /><link rel="alternate" hreflang="x-default" href="https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/" /> <script data-cfasync="false" data-pagespeed-no-defer>var gtm4wp_datalayer_name = "dataLayer";
var dataLayer = dataLayer || [];</script> <title>From DY Labs: The building blocks of effective open-source software</title><link rel="preload" as="font" href="https://www.dynamicyield.com/wp-content/themes/Divi/fonts/CircularXXTT/CircularXXWeb-Bold.woff2" crossorigin/><link rel="preload" as="font" href="https://www.dynamicyield.com/wp-content/themes/Divi/fonts/CircularXXTT/CircularXXWeb-Medium.woff2" crossorigin/><link rel="preload" as="font" href="https://www.dynamicyield.com/wp-content/themes/Divi/fonts/CircularXXTT/CircularXXWeb-Book.woff2" crossorigin/><meta name="description" content="Learn about our VP of Technology's journey in R&D and how his experiences have inspired him to tackle major, industry-wide technical problems." /><link rel="canonical" href="https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/" /><meta property="og:locale" content="en_US" /><meta property="og:type" content="article" /><meta property="og:title" content="From DY Labs: The building blocks of effective open-source software" /><meta property="og:description" content="Learn about our VP of Technology's journey in R&D and how his experiences have inspired him to tackle major, industry-wide technical problems." /><meta property="og:url" content="https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/" /><meta property="og:site_name" content="Mastercard Dynamic Yield" /><meta property="article:publisher" content="https://www.facebook.com/DynamicYield" /><meta property="article:published_time" content="2021-07-02T05:48:39+00:00" /><meta property="article:modified_time" content="2023-08-10T09:53:17+00:00" /><meta property="og:image" content="https://www.dynamicyield.com/wp-content/uploads/2021/07/funnel-rocket-social-1.png" /><meta property="og:image:width" content="1200" /><meta property="og:image:height" content="628" /><meta property="og:image:type" content="image/png" /><meta name="author" content="Elad Rosenheim" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:creator" content="@DynamicYield" /><meta name="twitter:site" content="@DynamicYield" /><meta name="twitter:label1" content="Written by" /><meta name="twitter:data1" content="Elad Rosenheim" /><meta name="twitter:label2" content="Est. reading time" /><meta name="twitter:data2" content="14 minutes" /> <script type="application/ld+json" class="yoast-schema-graph">{"@context":"https://schema.org","@graph":[{"@type":"Article","@id":"https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/#article","isPartOf":{"@id":"https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/"},"author":[{"@id":"https://www.dynamicyield.com/#/schema/person/7498e40640dac0dd78aca5c263b97ecf"}],"headline":"Going for gold: The building blocks of effective open-source software ","datePublished":"2021-07-02T05:48:39+00:00","dateModified":"2023-08-10T09:53:17+00:00","mainEntityOfPage":{"@id":"https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/"},"wordCount":2827,"commentCount":0,"publisher":{"@id":"https://www.dynamicyield.com/#organization"},"image":{"@id":"https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/#primaryimage"},"thumbnailUrl":"https://www.dynamicyield.com/wp-content/uploads/2021/07/funnel-rocket-blog-1.png","keywords":["DY Labs","Engineering","R&D"],"articleSection":["Product"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/#respond"]}]},{"@type":"WebPage","@id":"https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/","url":"https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/","name":"From DY Labs: The building blocks of effective open-source software","isPartOf":{"@id":"https://www.dynamicyield.com/#website"},"primaryImageOfPage":{"@id":"https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/#primaryimage"},"image":{"@id":"https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/#primaryimage"},"thumbnailUrl":"https://www.dynamicyield.com/wp-content/uploads/2021/07/funnel-rocket-blog-1.png","datePublished":"2021-07-02T05:48:39+00:00","dateModified":"2023-08-10T09:53:17+00:00","description":"Learn about our VP of Technology's journey in R&D and how his experiences have inspired him to tackle major, industry-wide technical problems.","breadcrumb":{"@id":"https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/#primaryimage","url":"https://www.dynamicyield.com/wp-content/uploads/2021/07/funnel-rocket-blog-1.png","contentUrl":"https://www.dynamicyield.com/wp-content/uploads/2021/07/funnel-rocket-blog-1.png","width":795,"height":320,"caption":"funnel rocket building blocks"},{"@type":"BreadcrumbList","@id":"https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://www.dynamicyield.com/"},{"@type":"ListItem","position":2,"name":"Going for gold: The building blocks of effective open-source software "}]},{"@type":"WebSite","@id":"https://www.dynamicyield.com/#website","url":"https://www.dynamicyield.com/","name":"Mastercard Dynamic Yield","description":"","publisher":{"@id":"https://www.dynamicyield.com/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://www.dynamicyield.com/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https://www.dynamicyield.com/#organization","name":"Mastercard Dynamic Yield","url":"https://www.dynamicyield.com/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https://www.dynamicyield.com/#/schema/logo/image/","url":"https://www.dynamicyield.com/wp-content/uploads/2019/10/DY-Hero_Logo-Black@x2.png","contentUrl":"https://www.dynamicyield.com/wp-content/uploads/2019/10/DY-Hero_Logo-Black@x2.png","width":458,"height":458,"caption":"Mastercard Dynamic Yield"},"image":{"@id":"https://www.dynamicyield.com/#/schema/logo/image/"},"sameAs":["https://www.facebook.com/DynamicYield","https://x.com/DynamicYield","https://www.instagram.com/dynamic.yield/","https://www.linkedin.com/company/dynamic-yield","http://www.pinterest.com/dynamicyield/","https://www.youtube.com/channel/UCPWEcR8lQRadVKYW8H4sndQ","https://en.wikipedia.org/wiki/Dynamic_Yield"]},{"@type":"Person","@id":"https://www.dynamicyield.com/#/schema/person/7498e40640dac0dd78aca5c263b97ecf","name":"Elad Rosenheim","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https://www.dynamicyield.com/#/schema/person/image/01b84b68e35295cd1c8b122801839de2","url":"https://secure.gravatar.com/avatar/219d268be8777d79c07971bba27a457a?s=96&d=mm&r=g","contentUrl":"https://secure.gravatar.com/avatar/219d268be8777d79c07971bba27a457a?s=96&d=mm&r=g","caption":"Elad Rosenheim"},"description":"Elad is the VP of Technology at Dynamic Yield, in charge of overseeing current and future architecture, mentoring developers, and designing for scale.","url":"https://www.dynamicyield.com/blog/author/elad/"}]}</script> <link rel='dns-prefetch' href='//pages.dynamicyield.com' /><link rel='dns-prefetch' href='//cdnjs.cloudflare.com' /><link rel="alternate" type="application/rss+xml" title="Mastercard Dynamic Yield » Feed" href="https://www.dynamicyield.com/feed/" /><link rel="alternate" type="application/rss+xml" title="Mastercard Dynamic Yield » Comments Feed" href="https://www.dynamicyield.com/comments/feed/" /><link rel="alternate" type="application/rss+xml" title="Mastercard Dynamic Yield » Going for gold: The building blocks of effective open-source software Comments Feed" href="https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/feed/" /><meta content="Divi v." name="generator"/><link rel='stylesheet' id='sbi_styles-css' href='https://www.dynamicyield.com/wp-content/plugins/instagram-feed/css/sbi-styles.min.css?ver=6.2.6' type='text/css' media='all' /><style id='wp-emoji-styles-inline-css' type='text/css'>img.wp-smiley, img.emoji {
display: inline !important;
border: none !important;
box-shadow: none !important;
height: 1em !important;
width: 1em !important;
margin: 0 0.07em !important;
vertical-align: -0.1em !important;
background: none !important;
padding: 0 !important;
}</style><link rel='stylesheet' id='wp-block-library-css' href='https://www.dynamicyield.com/wp-includes/css/dist/block-library/style.min.css?ver=935c7f8ce03960b02800bc8ae3231df8' type='text/css' media='all' /><style id='classic-theme-styles-inline-css' type='text/css'>/*! This file is auto-generated */
.wp-block-button__link{color:#fff;background-color:#32373c;border-radius:9999px;box-shadow:none;text-decoration:none;padding:calc(.667em + 2px) calc(1.333em + 2px);font-size:1.125em}.wp-block-file__button{background:#32373c;color:#fff;text-decoration:none}</style><style id='global-styles-inline-css' type='text/css'>body{--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}body .is-layout-flex > *{margin: 0;}body .is-layout-grid{display: grid;}body .is-layout-grid > *{margin: 0;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}
.wp-block-navigation a:where(:not(.wp-element-button)){color: inherit;}
:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}
:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}
.wp-block-pullquote{font-size: 1.5em;line-height: 1.6;}</style><link rel='stylesheet' id='rfw-style-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_7c036e0987ef80b703d7eb1abf922895.css?ver=2026020735' type='text/css' media='all' /><link rel='stylesheet' id='divi-style-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_ab3666a686d3dac03fd3032e5757637e.css?ver=935c7f8ce03960b02800bc8ae3231df8' type='text/css' media='all' /><link rel='stylesheet' id='ctt-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_f1d1b2f761cf3768f427cdc5c4c2544b.css?ver=935c7f8ce03960b02800bc8ae3231df8' type='text/css' media='all' /><link rel='stylesheet' id='inline-tweet-sharer-style-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_daa32ca85e114a0c6e5d1432c89237f3.css?ver=2.6.4' type='text/css' media='all' /><link rel='stylesheet' id='et_lb_modules-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_c0102af27938567cb82cc02e4da3a673.css?ver=2.4' type='text/css' media='all' /><link rel='stylesheet' id='et-shortcodes-css-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_40cb404848bc2e556105c8aea77f29aa.css?ver=3.0' type='text/css' media='all' /><link rel='stylesheet' id='et-shortcodes-responsive-css-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_3a30a77569bc4544b9465acbee8e5f97.css?ver=3.0' type='text/css' media='all' /><link rel='stylesheet' id='wp-featherlight-css' href='https://www.dynamicyield.com/wp-content/plugins/wp-featherlight/css/wp-featherlight.min.css?ver=1.3.4' type='text/css' media='all' /><link rel='stylesheet' id='baskerville-font-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_8c23179f030d02e0065d2054eab34279.css?ver=935c7f8ce03960b02800bc8ae3231df8' type='text/css' media='all' /><link rel='stylesheet' id='markformc-font-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_0eb51906eca648ca4559d0a03b898d83.css?ver=935c7f8ce03960b02800bc8ae3231df8' type='text/css' media='all' /><link rel='stylesheet' id='mackinac-font-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_9c8fec2609ebc9764a6e16471d9451ae.css?ver=935c7f8ce03960b02800bc8ae3231df8' type='text/css' media='all' /><link rel='stylesheet' id='button-pulse-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_4cabc8dd29eaa9af7bf2df62f1c40af9.css?ver=935c7f8ce03960b02800bc8ae3231df8' type='text/css' media='all' /><link rel='stylesheet' id='fontawesome-css' href='https://www.dynamicyield.com/wp-content/themes/Divi/custom/font-awesome/css/font-awesome.min.css' type='text/css' media='all' /><link rel='stylesheet' id='bootstrap-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_d375e60add46d8de26a78728b517660f.css' type='text/css' media='all' /><link rel='stylesheet' id='slick-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_13b1b6672b8cfb0d9ae7f899f1c42875.css' type='text/css' media='all' /><link rel='stylesheet' id='slick-theme-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_f9faba678c4d6dcfdde69e5b11b37a2e.css' type='text/css' media='all' /><link rel='stylesheet' id='custom-theme-style-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_57f41281576414370c141cd00d2a80a9.css?ver=26.27' type='text/css' media='all' /><link rel='stylesheet' id='custom-style-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_417039b6d54561fe1e8c94ee67cd902c.css?ver=26.27' type='text/css' media='all' /><link rel='stylesheet' id='header-style-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_d75ad7543415df427913a5fe91606386.css?ver=26.27' type='text/css' media='all' /><link rel='stylesheet' id='footer-style-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_25400e1cfd7099cc557083769c928231.css?ver=26.27' type='text/css' media='all' /><link rel='stylesheet' id='video_tabs_module-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_f1109a8bc8c46ec9f2205cc8603c132f.css?ver=26.27' type='text/css' media='all' /><link rel='stylesheet' id='select2-css' href='https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css' type='text/css' media='all' /><link rel='stylesheet' id='post-checklist-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_ede7f9aa4d78ac997ea5e48f5d511400.css?ver=26.27' type='text/css' media='all' /><link rel='stylesheet' id='post-event-cards-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_d02c1d48c2c1fde18d405f087a0fe833.css?ver=26.27' type='text/css' media='all' /><link rel='stylesheet' id='mkto-reset-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_d117c8ecde800f5dccd137c16bab71af.css?ver=26.27' type='text/css' media='all' /><link rel='stylesheet' id='learning-center-general-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_73dd3b78cf6e21c28be39db6740774b1.css?ver=26.27' type='text/css' media='all' /><link rel='stylesheet' id='article-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_e1d850b2d8d6fd6331ad74bd35ddde51.css?ver=1772307322' type='text/css' media='all' /><link rel='stylesheet' id='customers-shortcode-css' href='https://www.dynamicyield.com/wp-content/cache/autoptimize/css/autoptimize_single_c6bf61e9c8beb560d64d119f58757b8b.css?ver=26.27' type='text/css' media='all' /> <script type="text/javascript" src="https://www.dynamicyield.com/wp-includes/js/jquery/jquery.min.js?ver=3.7.1" id="jquery-core-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-includes/js/jquery/jquery-migrate.min.js?ver=3.4.1" id="jquery-migrate-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_dbdab0f35217f6041eb7e2028dc94ba4.js?ver=2.6.4" id="inline-tweet-sharer-js-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/themes/Divi/js/blazy.min.js" id="blazy-js"></script> <script type="text/javascript" src="//pages.dynamicyield.com/js/forms2/js/forms2.min.js?ver=21.85" id="mkto-form-script-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_db6be3b57dba139e789fec1a78186c8e.js?ver=21.85" id="learning-center-js-js"></script> <link rel="https://api.w.org/" href="https://www.dynamicyield.com/wp-json/" /><link rel="alternate" type="application/json" href="https://www.dynamicyield.com/wp-json/wp/v2/posts/160194" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://www.dynamicyield.com/xmlrpc.php?rsd" /><link rel='shortlink' href='https://www.dynamicyield.com/?p=160194' /><link rel="alternate" type="application/json+oembed" href="https://www.dynamicyield.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.dynamicyield.com%2Fblog%2Fdy-labs-building-blocks-open-source%2F" /><link rel="alternate" type="text/xml+oembed" href="https://www.dynamicyield.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.dynamicyield.com%2Fblog%2Fdy-labs-building-blocks-open-source%2F&format=xml" /><meta name="generator" content="WPML ver:4.6.8 stt:1,4,3,28,2;" /> <script type="text/javascript">(function(url){
if(/(?:Chrome\/26\.0\.1410\.63 Safari\/537\.31|WordfenceTestMonBot)/.test(navigator.userAgent)){ return; }
var addEvent = function(evt, handler) {
if (window.addEventListener) {
document.addEventListener(evt, handler, false);
} else if (window.attachEvent) {
document.attachEvent('on' + evt, handler);
}
};
var removeEvent = function(evt, handler) {
if (window.removeEventListener) {
document.removeEventListener(evt, handler, false);
} else if (window.detachEvent) {
document.detachEvent('on' + evt, handler);
}
};
var evts = 'contextmenu dblclick drag dragend dragenter dragleave dragover dragstart drop keydown keypress keyup mousedown mousemove mouseout mouseover mouseup mousewheel scroll'.split(' ');
var logHuman = function() {
if (window.wfLogHumanRan) { return; }
window.wfLogHumanRan = true;
var wfscr = document.createElement('script');
wfscr.type = 'text/javascript';
wfscr.async = true;
wfscr.src = url + '&r=' + Math.random();
(document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(wfscr);
for (var i = 0; i < evts.length; i++) {
removeEvent(evts[i], logHuman);
}
};
for (var i = 0; i < evts.length; i++) {
addEvent(evts[i], logHuman);
}
})('//www.dynamicyield.com/?wordfence_lh=1&hid=67004F143EC60BB70AE9B89262A2C408');</script>
<script data-cfasync="false" data-pagespeed-no-defer>var dataLayer_content = {"visitorLoginState":"logged-out","visitorType":"visitor-logged-out","pagePostType":"post","pagePostType2":"single-post","pageCategory":["product"],"pagePostAuthor":"Elad Rosenheim","pagePostDate":"July 2, 2021","pagePostDateYear":"2021","pagePostDateMonth":"07","pagePostDateDay":"02","pagePostDateDayName":"Friday","pagePostDateHour":"01","pagePostDateMinute":"48","pagePostDateIso":"2021-07-02T01:48:39-04:00","pagePostDateUnix":1625190519};
dataLayer.push( dataLayer_content );</script> <script type="text/javascript">console.warn && console.warn("[GTM4WP] Google Tag Manager container code placement set to OFF !!!");
console.warn && console.warn("[GTM4WP] Data layer codes are active but GTM container must be loaded using custom coding !!!");</script> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=3.0, user-scalable=1" /><link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16"><link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32"><link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96"><link rel="icon" type="image/png" href="/favicon-180x180.png" sizes="180x180"><link rel="icon" type="image/png" href="/favicon-192x192.png" sizes="192x192"><link rel="icon" type="image/png" href="/favicon-194x194.png" sizes="194x194"><link rel="shortcut icon" href="/favicon.ico"> <script type="text/javascript" data-noptimize>function dy_bind_adobe_mkto_events(form, form_id, form_name) {
// Init the adobeDataLayer object
window.adobeDataLayer = window.adobeDataLayer || [];
var focus_reported = false;
var form_completed = false;
var form_started_reported = false;
// Monitor input interactions - first focus (form start)
form.getFormElem().find('input, select').on('focus', function() {
// Only if it hasn't been reported yet
if(! focus_reported) {
focus_reported = true;
form_started_reported = true;
adobeDataLayer.push({
"event": "form_start",
"trackAction": {
"formName": form_name,
"formID": form_id,
"zoomInfo": localStorage.ZoomInfoData !== undefined,
}
});
}
});
// Detect dropoff if the form hasn't been completed
window.addEventListener("beforeunload", function(event) {
if (form_completed) return;
var filledLabels = [];
var count = 0;
form.getFormElem().find('input, select').each(function() {
var value = this.value && this.value.trim();
if (value) {
var label = form.getFormElem().find("label[for='" + this.id + "']").text().trim();
if (label) {
filledLabels.push(label);
count++;
}
}
});
if (count > 0) {
adobeDataLayer.push({
"event": "form_dropoff",
"formInfo": {
"formName": form_name,
"formID": form_id,
"zoomInfo": localStorage.ZoomInfoData !== undefined,
"completedFields": {
"labels": filledLabels.join("|"),
"count": count.toString()
}
}
});
}
});
// Hook into successful submission
form.onSuccess(function(values, followUpUrl) {
if(form_started_reported) {
// Report form completed
form_completed = true;
// Send an Adobe Analytics DataLayer event
adobeDataLayer.push({
"event": "form_complete",
"formInfo": {
"formName": form_name,
"formID": form_id,
"zoomInfo": localStorage.ZoomInfoData !== undefined,
"successAction": {
"action": "redirect",
"redirectUrl": followUpUrl
}
}
});
}
});
}
function dy_bind_adobe_cta_event(cta, cta_type, cta_section) {
var cta_name = cta.text().trim(),
cta_url,
page_url = window.location.href;
// const domainName = window.location.origin;
if (cta.attr('href') !== undefined) {
// cta_url = domainName + cta.attr('href');
cta_url = cta.attr('href');
} else {
cta_url = page_url;
}
adobeDataLayer.push({
"event": "ctaClick",
"clickInfo": {
"ctaName": cta_name,
"ctaType": cta_type,
"destinationURL": cta_url,
"ctaLocation": page_url,
"ctaSection": cta_section
}
});
}</script> <link rel="shortcut icon" href="https://www.dynamicyield.com/wp-content/uploads/2018/11/favicon-194x194.png" /><link rel="amphtml" href="https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/amp/"></head><body class="post-template-default single single-post postid-160194 single-format-standard wp-featherlight-captions et_fixed_nav et_right_sidebar gecko et_includes_sidebar elementor-default default_header"><div id="page-container"><header id="main-header" class="et_nav_text_color_dark"
style="background: #fff;"><div class="container-fluid clearfix"><div class="dy-header-logo"> <a href="https://www.dynamicyield.com/"
class="main-logo-container"><div id="logo_symbol"><svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" id="Layer_1" x="0" y="0" version="1.1" viewBox="0 0 266.8 164.9"><g id="XMLID_23_"><path fill="#ff5f00" d="M97.3 17.5h72.2v129.7H97.3z"/><path id="XMLID_35_" fill="#eb001b" d="M101.9 82.4c0-26.3 12.3-49.7 31.5-64.8-14-11-31.7-17.6-51-17.6C36.9-.1 0 36.8 0 82.4c0 45.5 36.9 82.5 82.5 82.5 19.2 0 36.9-6.6 51-17.6-19.3-15.2-31.6-38.6-31.6-64.9z"/><path d="M266.8 82.4c0 45.5-36.9 82.5-82.5 82.5-19.2 0-36.9-6.6-51-17.6 19.2-15.1 31.5-38.5 31.5-64.8s-12.3-49.7-31.5-64.8c14-11 31.7-17.6 51-17.6 45.6-.2 82.5 36.7 82.5 82.3zM259 133.5v-2.7h1.1v-.5h-2.7v.5h1.1v2.7h.5zm5.3 0v-3.2h-.8l-1 2.2-1-2.2h-.8v3.2h.6v-2.4l.9 2.1h.6l.9-2.1v2.4h.6z" fill="#f79e1b"/></g></svg></div> </a></div><div id="et-top-navigation" class="cd-morph-dropdown"><nav id="top-menu-nav" class="main-nav"><ul id="top-menu" class="nav"></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li></li><li class="has-dropdown product menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children" data-content="product" title=""> <a href="">Product</a></li><li class="has-dropdown solutions menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children" data-content="solutions" title=""> <a href="">Solutions</a></li><li class="has-dropdown why_dy menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children" data-content="why-dynamic-yield" title="Why DY"> <a href="">Why Dynamic Yield</a></li><li class="has-dropdown company menu-has-cta menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children" data-content="company" title=""> <a href="">Company</a></li><li class="has-dropdown learning_center menu-has-cta top-link-use-cases menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children" data-content="learning-center" title=""> <a href="">Learning Center</a></li><li class="contact top-link walker-last mobile-only menu-item menu-item-type-post_type menu-item-object-page" data-content="connect-with-us" title=""> <a href="https://www.dynamicyield.com/contact/"><span class="button-arrow">Connect with us</span></a></li></ul></nav><div class="morph-dropdown-wrapper"><div class="dropdown-list"><div class="dropdown-tooltip"></div><ul><li id="product" class="dropdown links"><a href="" class="label">Product</a><div class="content"><ul><li class="intro"><div class="exp_os-wrapper"><h2>Experience OS</h2><ul class="links-list"><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="https://www.dynamicyield.com/experience-os/"><span class="menu-banner-img-wrap"><img class="menu-banner-img-desktop" src="/wp-content/uploads/2024/10/expos-nav-updated.png" width="218" height="131" /><img class="menu-banner-img-mobile" src="/wp-content/uploads/2024/10/expos-nav-updated-mobile.png" width="114" height="98" /></span><span class="menu-cta-text-wrap"><span class="menu-cta-subtitle">Get an overview of Dynamic Yield’s product and see why we’re known as the Experience OS.</span> <span class="menu-cta-button">Learn more →</span></span></a></li></ul></div></li><li class="left"><div class="key_caps-wrapper"><h2>Core Capabilities</h2><ul class="links-list"><li class="key-caps-segment menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/segmentation/"><svg version="1.1" id="audience" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 30 30" style="enable-background:new 0 0 30 30;" xml:space="preserve"><path id="audience-green" fill="#4FB294" d="M9.291,30H30V9.291C18.562737,9.291,9.291,18.562737,9.291,30z"/><path id="audience-black" d="M12.527,15.947C9.240353,12.385597,4.806085,10.093244,0,9.471V30h7.639 C7.632218,24.897682,9.35532,19.943764,12.527,15.947z"/><circle id="audience-circle" fill="#4FB294" cx="15" cy="4.967" r="4.967"/></svg>Segmentation<span>Identify, build, and analyze audiences</span></a></li><li class="key-caps-omnichannel menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/targeting/"><svg version="1.1" id="personalization" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 20.987 30" style="enable-background:new 0 0 20.987 30;" xml:space="preserve"><path id="personalization-black-2" d="M20.987,19.507c0,5.795401-4.698099,10.4935-10.4935,10.4935S0,25.302401,0,19.507H20.987z"/><path id="personalization-pink" fill="#EE3968" d="M18.143,10.245c0,4.224978-3.425022,7.649999-7.65,7.649999S2.842999,14.469978,2.842999,10.245 H18.143z"/><circle id="personalization-black-1" cx="10.494" cy="4.307" r="4.307"/></svg>Targeting<span>Serve each customer with unique offers</span></a></li><li class="key-caps-recs menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/recommendations/"><svg version="1.1" id="recs" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 30 30" style="enable-background:new 0 0 30 30;" xml:space="preserve"><path id="recs_4" d="M15.953,30H30V15.953H15.953V30z"/> <path id="recs_3" d="M0,15.953V30h14.047V15.953H0z"/><path id="recs_2" fill="#FFA354" d="M30,14.047V0H15.953v14.047H30z"/><path id="recs_1" d="M14.047,0H0v14.047h14.047V0z"/></svg>Recommendations<span>Algorithmically predict customers’ interests</span></a></li><li class="key-caps-email menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/journey-orchestration/"><svg version="1.1" id="trigger" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 26.017 30" style="enable-background:new 0 0 26.017 30;" xml:space="preserve"><path id="trigger-black" d="M14.017,12h12l-12,18V12z"/><path id="trigger-purple" fill="#5D39B9" d="M12,18H0L12,0V18z"/></svg>Journey Orchestration<span>Reach customers at critical moments</span></a></li><li class="key-caps-abtesting menu-item menu-item-type-custom menu-item-object-custom"><a href="/optimization/"><svg version="1.1" id="testing" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 28.713001 30" style="enable-background:new 0 0 28.713001 30;" xml:space="preserve"><path id="testing-blue" fill="#6BDADA" d="M15.831,0c7.114532,0,12.882001,5.767468,12.882001,12.882S22.945532,25.764,15.831,25.764l0,0V0z"/><path id="testing-black" d="M12.882,30C5.767468,30,0,24.232533,0,17.118S5.767468,4.236,12.882,4.236V30z"/></svg>Optimization<span>Experiment on any digital property</span></a></li><li class="key-caps-search menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/search/"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <g clip-path="url(#clip0_4082_5186)" id="cap-search-svg-bg"> <path d="M11.6757 9.81054C8.73958 9.81054 6.35089 7.42177 6.35089 4.48562C6.35089 2.62899 7.30664 0.992133 8.75134 0.0388074C8.50309 0.0155936 8.25193 0.00238037 7.99762 0.00238037C3.58066 0.00238037 0 3.58304 0 8C0 12.417 3.58066 15.9976 7.99762 15.9976C12.4146 15.9976 15.9952 12.417 15.9952 8C15.9952 7.86848 15.9916 7.73782 15.9853 7.60785C15.0166 8.94122 13.4462 9.81054 11.6757 9.81054Z" fill="black"/> <path id="cap-search-svg-circle" d="M11.6757 0.161346C11.2226 0.161346 10.7857 0.231773 10.3749 0.361649C8.62429 0.915114 7.35156 2.55436 7.35156 4.48561C7.35156 6.87003 9.29141 8.80988 11.6757 8.80988C13.5373 8.80988 15.1277 7.62753 15.7358 5.97437C15.9066 5.51 16 5.00851 16 4.48561C16 2.10119 14.0602 0.161346 11.6757 0.161346Z" fill="#FFC61E"/> </g> <defs> <clipPath id="clip0_4082_5186"> <rect width="16" height="16" fill="white"/> </clipPath> </defs> </svg>Search<span>Help customers find what they want</span></a></li></ul></div></li><li class="right"><div class="scale-wrapper"><h2>Made for Scale</h2><ul class="links-list"><li class="key_caps-element menu-item menu-item-type-custom menu-item-object-custom"><a href="/element/">Element<span>A groundbreaking new dimension of hyper-personalization</span></a></li><li class="key_caps-adaptml menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/ai/">AI & Automation<span>Increase automation, lower operational costs, and drive more revenue with a holistic AI personalization system</span></a></li><li class="key_caps-apis menu-item menu-item-type-custom menu-item-object-custom"><a href="https://www.dynamicyield.com/experience-apis/">Experience APIs<span>Give developers the tools they need to build the best customer experiences</span></a></li><li class="key_caps-enterprise menu-item menu-item-type-custom menu-item-object-custom"><a href="https://www.dynamicyield.com/enterprise-grade-personalization/">Enterprise solutions<span>Scale with security, privacy, and compliance, made for the enterprise</span></a></li></ul></div></li></ul><a href="/shopping-muse/" target="" class="banner"><div class="menu-banner"><span class="menu-cta-text"><strong>Meet Shopping Muse: </strong> Conversational commerce meets cutting-edge personalization.</span> <span class="menu-cta-button">Learn more →</span></div></a></div></li><li id="solutions" class="dropdown links"><a href="" class="label">Solutions</a><div class="content"><ul><li class="left"><div class="industries-wrapper"><h2>Industries</h2><ul class="links-list"><li class="industry-ecomm menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/ecommerce/">eCommerce</a></li><li class="industry-finserv menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/financial-services/">Financial Services</a></li><li class="industry-qsr menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/restaurants/">Restaurants</a></li><li class="industry-grocery menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/grocery/">Grocery</a></li><li class="industry-b2b menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/b2b-ecommerce/">B2B eCommerce</a></li><li class="industry-travel menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/travel/">Travel</a></li><li class="industry-gaming menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/gaming/">iGaming</a></li><li class="industry-media menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/media/">Media</a></li></ul></div></li><li class="right"><div class="channels-wrapper"><h2>Channels</h2><ul class="links-list"><li class="channels-web menu-item menu-item-type-custom menu-item-object-custom"><a href="/web/">Web<span>Create customer-centric web experiences</span></a></li><li class="channels-email menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/channels/email/">Email<span>Personalize emails with a no-code builder</span></a></li><li class="channels-mobile-apps menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/mobile/">Apps<span>Optimize mobile app experiences</span></a></li><li class="channels-ads menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/advertising/">Ads<span>Improve customer acquisition results</span></a></li></ul></div></li></ul></div></li><li id="why-dynamic-yield" class="dropdown links"><a href="" class="label">Why Dynamic Yield</a><div class="content"><ul><li class="impact-wrapper"><h2>Proven impact and success services</h2><ul class="links-list"><li class=" menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/clients/">Select customers</a></li><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="/case-studies/">Case studies</a></li><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="/customer-success/">Customer success services</a></li></ul></li><li class="scale-wrapper"><h2>Built for scale</h2><ul class="links-list"><li class=" menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/enterprise-grade-personalization/">Enterprise-grade solutions</a></li><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="/adaptml/">AI Technology</a></li><li class=" menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/gdpr-and-privacy/">GDPR and data privacy</a></li><li class=" menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/security/">Security</a></li><li class=" menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/compliance/">Compliance</a></li></ul></li><li class="network-wrapper"><h2>Robust partner network</h2><ul class="links-list"><li class=" menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/partners/">Partner library</a></li><li class=" menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/partner-program/">Partnership program</a></li><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="/partners/#technology-partners">Tech Partners and Integrations</a></li></ul></li><li class="resources-wrapper"><h2>Extensive product resources</h2><ul class="links-list"><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="https://support.dynamicyield.com/hc/en-us">Knowledge Base</a></li><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="http://academy.dynamicyield.com/">Academy & Certification</a></li><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="https://support.dynamicyield.com/hc/en-us/community/topics">Community</a></li><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="https://dy.dev/">API documentation</a></li></ul></li></ul><a href="https://www.dynamicyield.com/personalization-awards/" target="_self" class="banner"><div class="menu-banner"><div class="menu-cta--left"> <img src="/wp-content/uploads/2023/11/2023-award-badge.svg" width="60" height="60" /></div><div class="menu-cta--right"> <strong class="menu-cta-title">The Personalization Awards</strong> <span class="menu-cta-subtitle">Celebrating customers and partners setting the gold-standard for personalization</span> <span class="menu-cta-button">Learn more →</span></div></div></a></div></li><li id="company" class="dropdown button"><a href="" class="label">Company</a><div class="content"><ul class="links-list"><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="https://www.mastercard.com/us/en/for-the-world/about-us.html">About us</a></li><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="/blog/">Blog</a></li><li class=" menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/labs/">DY Labs</a></li><li class=" menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/careers/">Careers</a></li><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="https://events.dynamicyield.com/">Events</a></li><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="https://www.mastercard.com/us/en/news-and-trends/stories.html">Press</a></li><li class=" menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/awards-and-recognitions/">Awards</a></li><li class=" menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/contact/">Contact us</a></li><li class=" menu-item menu-item-type-custom menu-item-object-custom"><a href="/request-demo/">Request a demo</a></li></ul></div></li><li id="learning-center" class="dropdown links"><a href="" class="label">Learning Center</a><div class="content"><ul><li class="top"><ul class="links-list"><li class="resources-xp hidden-mobile menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/learn/">Take your knowledge to exponential levels</a></li><li class="hidden-desktop menu-item menu-item-type-custom menu-item-object-custom"><a href="/learn/">XP<sup>2</sup> Hub<span>Take your knowledge to exponential levels</span></a></li><li class="resources-paths menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/learning-paths/">Learning Paths<span>Curated courses on key skill areas</span></a></li><li class="resources-webinars menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/talks/">Talks<span>Engaging discussions taking place in CX</span></a></li><li class="resources-articles menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/articles/">Articles<span>An expansive collection of in-depth playbooks</span></a></li><li class="resources-glossary menu-item menu-item-type-custom menu-item-object-custom"><a href="/glossary-terms/">Encyclopedia<span>A glossary of experience optimization terms</span></a></li><li class="resources-use-cases menu-item menu-item-type-post_type menu-item-object-page"><a href="https://www.dynamicyield.com/personalization-examples/">Inspiration Library<span>Personalization examples from real brands</span></a></li><li class="resources-maturity menu-item menu-item-type-custom menu-item-object-custom"><a href="https://www.dynamicyield.com/personalization-maturity/"><strong class="badge-new">Personalization Maturity</strong><span>How global businesses prioritize personalization</span></a></li><li class="resources-guides menu-item menu-item-type-custom menu-item-object-custom"><a href="/guides/">Guides & reports<span>Comprehensive topic-specific materials</span></a></li><li class="resources-benchmarks menu-item menu-item-type-custom menu-item-object-custom"><a href="https://marketing.dynamicyield.com/benchmarks/">Benchmarks<span>Industry performance metrics and insights</span></a></li></ul></li><li class="bottom"><a href="/rooted-personalization/" target="_self"><div class="menu-banner"><div class="menu-cta--left"> <img src="/wp-content/uploads/2023/03/rooted-icon.svg" width="60" height="60" /></div><div class="menu-cta--right"> <strong class="menu-cta-title">Rooted Personalization<span>new</span></strong> <span class="menu-cta-subtitle">Learn a scalable methodology for building an audience-based personalization program.</span> <span class="menu-cta-button">Find out more →</span></div></div></a></li></ul></div></li><li class="contact top-link walker-last mobile-only menu-item menu-item-type-post_type menu-item-object-page" data-content="connect-with-us" title=""> <a href="https://www.dynamicyield.com/contact/"><span class="button-arrow">Connect with us</span></a></li></ul><div class="bg-layer" aria-hidden="true"></div></div></div></li></ul></nav></div><div class="topnav-buttons"><div class="language-switcher header-language-switcher"><ul><li>en<ul><li><a class="active" href="https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/">English</a></li><li><a href="https://www.dynamicyield.com/es/">Español</a></li><li><a href="https://www.dynamicyield.com/de/">Deutsch</a></li><li><a href="https://www.dynamicyield.com/fr/">Français</a></li><li><a href="https://www.dynamicyield.com/ja/">日本語</a></li></ul></li></li></ul></div> <a class="pulse-button v5 pulsed nav_btn" href="/request-demo/"> <span class="button-inner"> Talk to sales </span> </a> <a href="" class="nav-trigger"> Open Nav <span class="nav-trigger-box"><span class="nav-trigger-inner"></span></span> </a></div></div></header><div id="top-nav-backdrop"></div><div id="et-main-area"><div id="main-content"><div class="lc-container"><div id="content-area" class="clearfix"><header class="article-sticky-header"><div class="lc-header-container lc-flex"><div class="lc-header-logo"></div><div class="lc-header-title"> Going for gold: The building blocks of effective open-source software </div><div class="lc-header-right lc-flex"><ul class="lc-header-social lc-flex"><li class="et-social-icon"> <a href="#" title="Share on Facebook" class="icon" onclick="window.open('https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(document.URL) + '&t=' + encodeURIComponent(document.URL)); return false;"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 460.1990662 458.5138245"><path d="M460.1990662,230.0995331C460.1990662,103.0190277,357.1800232,0,230.0995331,0S0,103.0190277,0,230.0995331C0,338.011261,74.2903519,428.5578003,174.5126801,453.4230957V300.4146423H127.064209v-70.3151093h47.4484711v-30.2983704c0-78.3184433,35.4433594-114.619339,112.3326569-114.619339c14.5774536,0,39.730896,2.8583221,50.020874,5.7166443v63.7409363c-5.4308167-0.5716553-14.8633118-0.8574677-26.58255-0.8574677c-37.7300415,0-52.3075867,14.2916718-52.3075867,51.4501038v24.8674927h75.158783l-12.9122009,70.3151093h-62.246582v158.0991821C371.9082336,444.7527161,460.1990662,347.742981,460.1990662,230.0995331z"/></svg> </a></li><li class="et-social-icon"> <a href="#" title="Share on Linkedin" class="icon" onclick="window.open( 'https://www.linkedin.com/shareArticle?mini=true&url=' + encodeURIComponent(document.location.href)); return false;"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M100.28 448H7.4V148.9h92.88zM53.79 108.1C24.09 108.1 0 83.5 0 53.8a53.79 53.79 0 0 1 107.58 0c0 29.7-24.1 54.3-53.79 54.3zM447.9 448h-92.68V302.4c0-34.7-.7-79.2-48.29-79.2-48.29 0-55.69 37.7-55.69 76.7V448h-92.78V148.9h89.08v40.8h1.3c12.4-23.5 42.69-48.3 87.88-48.3 94 0 111.28 61.9 111.28 142.3V448z"/></svg> </a></li><li class="et-social-icon"> <a href="#" title="Tweet" class="icon" onclick="window.open('https://twitter.com/intent/tweet?text=' + encodeURIComponent(document.title) + ':%20' + encodeURIComponent(document.URL)); return false;"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z"/></svg> </a></li></ul><div class="topnav-buttons"> <a href="#" data-toggle="modal" data-target="#lc-subscription" class="btn-desktop-only pulse-button v5 topnav-btn"> <span class="button-inner"> XP² Newsletter </span> </a> <a href="/newsletter/" class="pulse-button v5 topnav-btn btn-mobile-only"> <span class="button-inner"> XP² Newsletter </span> </a></div></div></div><div class="lc-progress-wrap"><div class="lc-scroll-progress"></div></div></header><article id="post-160194" class="et_pb_post post-160194 post type-post status-publish format-standard has-post-thumbnail hentry category-product tag-dy-labs tag-engineering tag-rd"><div class="article-content"><div class="article-breadcrumbs"> <a href="https://www.dynamicyield.com/blog/" title="Blog">Blog</a><ul class="post-categories"><li><a href="https://www.dynamicyield.com/blog/category/product/" rel="category tag">Product</a></li></ul></div><h1 class="article-title">Going for gold: The building blocks of effective open-source software </h1><h2 class="article-excerpt">Read our VP of Technology's perspective on how his experiences in the field have pushed him and others to innovate and tackle challenges facing developers across industries, culminating in fresh open-source projects.</h2><div class="article-authors lc-flex"><div class="article-author-box lc-col lc-flex"><div class="article-author-image lc-col"><div class="entry_author_image"><img src="https://www.dynamicyield.com/wp-content/authors/elad-47.png" alt="Elad Rosenheim" width="76" height="76" /></div></div><div class="article-author-title lc-col"><div class="article-author-name"> <a href="https://www.dynamicyield.com/blog/author/elad/" title="Posts by Elad Rosenheim" rel="author">Elad Rosenheim</a></div><div class="article-author-title-text"> VP of Technology, Dynamic Yield</div></div></div></div><div class="entry-content article-entry-content"><p><i><span style="font-weight: 400;">This post is part one of a two-part series brought to you by DY Labs, an initiative by members of our Product and R&D departments who have a passion for experimentation and building developer resources for the greater digital marketing and engineering communities. This series focuses on the cohort’s latest project, </span></i><a href="https://github.com/DynamicYieldProjects/funnel-rocket"><i><span style="font-weight: 400;">Funnel Rocket</span></i></a><i><span style="font-weight: 400;">, which is a serverless query engine optimized for complex user-centric queries at scale. In part one, Elad Rosenheim, our VP of Technology, walks through his journey in the world of product and engineering and how his experiences in the field have pushed him and others to innovate and tackle challenges facing developers across industries in order to develop open-source solutions.</span></i></p><p><i><span style="font-weight: 400;">An earlier version of this post was previously published by Elad </span></i><a href="https://elad-rosenheim.medium.com/all-clusters-must-die-9a332bd93ccc" target="_blank" rel="noopener noreferrer"><i><span style="font-weight: 400;">on Medium</span></i></a><i><span style="font-weight: 400;">.</span></i></p><p><span style="font-weight: 400;">Over the last decade, we’ve experienced the rise and rise of open-source software for big data and big scale. That was indeed a big leap forward, yet I’ve become disillusioned with much of the surrounding hype. Rants aside, here’s where I think the underlying issues are, and most importantly – what we can do about it. It’s my personal take, so let’s start with my own personal story.</span></p><h2><span style="font-weight: 400;">From the dot-com bubble to the open-source era </span></h2><p><span style="font-weight: 400;">I can trace my first real job back to around 1998. During that period, real servers were still made by companies like Sun, running Solaris on expensive proprietary metal. I recall catching a glimpse of a purchase order for a few Sun Ultra workstations to roughly around 2000. One line item, in particular, caught my eyes, as I could directly compare it to my PC at home: a cool $150 for a CD drive, worth about $230 today. It’s very probable that this drive came in Sun’s iconic purple, thus exuding its commanding authority over the pedestrian CD drive in your home, but still — it didn’t feel right. Savvy young developers started pushing for Linux, and people rushed to join the first wave of the dot-com bubble.</span></p><p><span style="font-weight: 400;">Fast forward to 2013, when I joined a tiny startup – Dynamic Yield – and started working on “web-scale” problems in earnest. Up to that point, scale (to me) usually meant tuning a beastly Java application server doing maybe 100 requests per second at most, each request typically hitting the relational database a dozen times within a transaction. Every single request used to mean something important that someone cared about. Now, data has become a clickstream from across the web: hardly transaction-worthy, but coming in at thousands of requests per second, and growing fast.</span></p><p><span style="font-weight: 400;">The founding team already had their first database (a single MySQL instance) brought to its knees on that traffic and moved on to </span><a href="https://hbase.apache.org/" target="_blank" rel="noopener noreferrer"><span style="font-weight: 400;">Apache HBase</span></a><span style="font-weight: 400;"> for anything non-administrative. Before a year went by, I introduced </span><a href="https://redis.io/" target="_blank" rel="noopener noreferrer"><span style="font-weight: 400;">Redis</span></a><span style="font-weight: 400;"> for fast access to user data and </span><a href="https://www.elastic.co/" target="_blank" rel="noopener noreferrer"><span style="font-weight: 400;">Elasticsearch</span></a><span style="font-weight: 400;"> for ad-hoc analytics to our growing spiderweb of an architecture. We were deep in NoSQL territory now. For batch jobs, custom Java processes and clunky Hadoop MapReduce jobs started making way for the new shiny tech of the day: </span><a href="https://spark.apache.org/" target="_blank" rel="noopener noreferrer"><span style="font-weight: 400;">Apache Spark</span></a><span style="font-weight: 400;">. </span><a href="https://kafka.apache.org/"><span style="font-weight: 400;">Kafka</span></a><span style="font-weight: 400;"> and stream processing frameworks would come next.</span></p><p><span style="font-weight: 400;">Much of that new wealth of tools for scale was directly inspired by Google’s whitepapers. These marked a big shift in how scale and resilience were tackled or at least thought about.</span></p><p><span style="font-weight: 400;">First, it was about GFS<span style="font-weight: 400;"> (the Google File System) and </span><a href="https://static.googleusercontent.com/media/research.google.com/en//archive/mapreduce-osdi04.pdf" target="_blank" rel="noopener noreferrer"><span style="font-weight: 400;">MapReduce</span></a><span style="font-weight: 400;">, then </span><a href="https://static.googleusercontent.com/media/research.google.com/en//archive/bigtable-osdi06.pdf" target="_blank" rel="noopener noreferrer"><span style="font-weight: 400;">BigTable</span></a><span style="font-weight: 400;">. It pushed the wider tech community to think in terms of commodity hardware and inexpensive hard disks rather than purple hardware and RAID, relying on multiple replicas for high availability and distributing work. You realized hardware will fail and keep failing, and what you needed were tools that will happily skip over such road bumps with minimal fuss and grow in capacity as fast as you can throw new machines at ’em.</span></p><p><span style="font-weight: 400;">Not having to pay a hefty per-server license fee was a big plus. The concept of GFS inspired Apache HDFS, Google MapReduce’s principles were recast as Apache Hadoop M/R, and BigTable was remade as Apache HBase. Later on, Google’s </span><a href="https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/36632.pdf" target="_blank" rel="noopener noreferrer"><span style="font-weight: 400;">Dremel</span></a><span style="font-weight: 400;"> (which you probably know today in its SaaS incarnation — BigQuery) inspired the Parquet file format and a new generation of distributed query engines.</span></p><p><span style="font-weight: 400;">To me, these were exciting times – being able to scale so much with open source, provisioning new servers in hours or minutes! The promises of elasticity, cost efficiency, and high availability were, to a large extent, realized — especially if you had been accustomed to waiting months for servers, for IT priests to install a pricey NAS, or for the procurement of more commercial middleware licenses.</span></p><p><span style="font-weight: 400;">I guess this goes against the grain of nostalgia permeating so much of the discourse. Usually, it sounds something like, “We did so much in the old days with so little memory and no-nonsense, hand-polished code! Oh, these kids and their multi-megabyte JS bundles will never know…” I like to compare that to a tip I’ve learned from parenting: There is always someone who has achieved so much more with far less but is simply eager to tell you all about it. </span></p><h2><span style="font-weight: 400;">The burden of complexity</span></h2><p><span style="font-weight: 400;">It seems like you only get a look at the real, gnarly underbelly of a cluster at the worst times: during peak traffic periods, at nights, or on holidays.</span></p><p><span style="font-weight: 400;">There is a complexity to a cluster’s state management that just does not go away, and instead, is waiting to explode at some point. Here’s how it usually starts off, at least in my experience:</span><span style="font-weight: 400;"><br /> </span></p><ol><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Whether you’re managing a random-access database cluster, a batch processing, or a stream processing cluster, you get it to work initially and for a while, it seems to work!</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">You don’t really need to know how it elects a master, how it allocates and deallocates shards, how precious metadata is kept in sync, or what ZooKeeper actually does in there.</span></li></ol><p><span style="font-weight: 400;">At some point, you hit some unexpected threshold that’s really hard to predict because it’s related to your usage patterns, your specific load spikes, and things go awry. Sometimes, the system gets completely stuck, sometimes limping along and crying out loud in the log files. Often, it’s not a question of data size or volume as you might expect, but a more obscure limit being crossed. Your Elasticsearch cluster might be fine with 2,382 indices, but one day, you get to 2,407 and nodes start breaking, pulling the rest of them down with them to misery lane. I just made up these numbers —your metrics and thresholds are likely different, but you get the picture. </span></p><p><span style="font-weight: 400;">In the best-case scenario, you solve the issue at hand that day, but often, the same issue will repeat. This is where you need to step back and give it time. Sometimes, it takes weeks to stabilize things or even months to hunt down a recurring issue. And over time, this becomes a time suck. Sometimes, multiple and seemingly unrelated incidents happen to all blow up over a short period of time, and the team experiences fatigue from fighting multiple fires simultaneously. Eventually, you’ve put enough work hours and thrown enough extra resources at the problem (i.e. supplying a few more servers, giving it more headroom) and it goes away, but deep down, you know it will return. As a head of R&D, I know this can be extremely draining, because whether the fire is at team A, B, or C — it’s ultimately your fire as well, every single time. </span></p><p><span style="font-weight: 400;">Sometimes, people will respond to your troubles with how great and reliable their tooling is or was at company X: “We’re using this awesome database Y and have never had any significant issue!” or “You’re over-complicating it, just use Z like us and your problems will go away.” However, this can often be over-simplifying the core issue at hand, skirting around the real complexity and nuances of your end goal. And over time, I’ve found solace in focusing on tending to my roots, because choosing to neglect them is only sustainable for so long.</span></p><h2><span style="font-weight: 400;">Let’s talk about elasticity</span></h2><p><span style="font-weight: 400;">Operational complexity is an enduring burden, but I should also mention limited elasticity and its friend, high cost. While tools do get better in that respect, what may have been considered “elastic” in 2012 is simply not what I’d call elastic today.</span></p><p><span style="font-weight: 400;">Let’s take Apache Spark for example. There’s still a steady stream of people going into Big Data who think it will solve all their problems, but if you’ve spent significant time with it, you know that in order for your jobs to work well, you need to carefully adjust the amount of RAM vs. CPU used, you need to dive into config settings, and perhaps even tinker with Garbage Collection a bit. You need to analyze the “naive” </span><a href="https://data-flair.training/blogs/dag-in-apache-spark" target="_blank" rel="noopener noreferrer"><span style="font-weight: 400;">DAG</span></a><span style="font-weight: 400;"> it generates for your code to find choke points, then modify the code so it’s less about the cleanest functional abstraction and more about actual efficiency. In our case, we also needed to override some classes. And that’s how this song goes: care-free big data processing by high-level abstractions rarely lives up to the hype.</span></p><p><span style="font-weight: 400;">The challenge goes further, however.</span></p><p><span style="font-weight: 400;">One idea that Apache Hadoop pushed for since its inception was the ability to build a nice big cluster of commodity servers in order to throw several jobs from different teams at different times at its resource manager (nowadays known as </span><a href="https://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-site/" target="_blank" rel="noopener noreferrer"><span style="font-weight: 400;">YARN</span></a><span style="font-weight: 400;">), letting it figure out which resources each job needs and how to fit all these jobs nicely. The concept was to think about the capacity of the cluster as an aggregate of its resources: this much CPU, storage, memory. You would scale that out as necessary, while R&D teams kept churning out new jobs to submit. That idea pretty much made its way into Spark as well.</span></p><p><span style="font-weight: 400;">The problem is, one single cluster really doesn’t like juggling multiple jobs with very different needs in terms of computing, memory, and storage. What you get instead is a constant battle for resources, delays, and occasional failures. Your cluster will typically be in one of two modes:</span><span style="font-weight: 400;"><br /> </span></p><ol><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Over-provisioned to have room for extra work (read: idle resources that you pay for), or</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Under-provisioned, leaving you wishing it was easy or quick to scale depending on how well jobs progress right at this moment (I’m not saying it’s not possible, but it’s definitely not easy, quick or out-of-the-box)</span></li></ol><p><span style="font-weight: 400;">Web servers usually “have one job” and give you the ability to measure their maximum capacity as X requests per second. They rely on databases and backend servers, but they don’t need to know each other, let alone pass huge chunks of data between them over the network or thrash the disks. Data processing clusters do all these different things, concurrently, and never exactly at the same exact moment, which may cause issues. If you run into such problems, you’ll probably start managing multiple clusters, each configured to its needs and with its own headroom. However, provisioning these multiple clusters takes precious time, and operating them is still a hassle. Even a single job in isolation has multiple stages which stress different resource types (CPU, memory, disk, network), which makes optimal resource planning a challenge, even with multiple dedicated clusters.</span></p><p><span style="font-weight: 400;">You could get some of that work off your shoulders if you go for a managed service, but the “management tax” can easily cost outlandish amounts of money as you scale. If you’re already paying, say, $1 million a year for self-managed resources on the cloud, you have to ask yourself: Are we willing to pay 1.5x-2x that price tag to receive a managed-to-an-extent service?</span></p><p><span style="font-weight: 400;">New technologies (e.g. k8s operators) do provide us with faster provisioning and better resource utilization. There is one thing they cannot solve for, however: precious engineering time spent to thoroughly profile and tune misbehaving components, which in turn makes it very tempting to throw ever more compute resources at the problem. Over time, these inefficiencies accumulate, and as the organization grows, you’ll rack up a pretty significant bill to manage the entire system without an efficient solution. </span></p><h2><span style="font-weight: 400;">Gradual improvements over time</span></h2><p><span style="font-weight: 400;">Once your Spark cluster is properly set-up and running well, it can output huge amounts of data quickly when it reaches the result-writing stage. If the cluster is running multiple jobs, these writes come in periodic bursts.</span></p><p><span style="font-weight: 400;">Now, assume you want these results written into external systems, e.g. SQL databases, Redis, Elasticsearch, Cassandra. It’s all too easy for Spark to overwhelm or significantly impair any database with these big writes – I’ve even seen it break a cluster’s internal replication, which is a nightmare scenario.</span></p><p><span style="font-weight: 400;">You can’t really expect Elasticsearch to grow from, say, 200 cores to 1,000 for exactly the duration where you need to index things in bulk, then shrink back to 200 immediately afterwards. Instead, there are various things you can do:</span></p><ul><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Aggressively throttle down the output from Spark — i.e. spend money being near-idle on the Spark side</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Write and manage a different component to read Spark’s output and perform the indexing (meaning dev time and operations)</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Over-provision Elasticsearch (= more money)</span></li></ul><p><b>In other words, not really the elasticity I was hoping for.</b></p><p><span style="font-weight: 400;">Over time, patterns have evolved to alleviate some of these pain: Apache Kafka is frequently used as the “great decoupler”, allowing multiple receiving ends to consume data at their own pace, go down for maintenance, etc. Kafka, though, is another expensive piece of the puzzle that is definitely not as easy to scale or as resilient as the initial hype had me believing.</span></p><p><span style="font-weight: 400;">On the storage front, there have been improvements as well: instead of using HDFS, we switched to S3 for all batch outputs so we don’t need to worry about HDD size or filesystem metadata processes. That means giving up on the once-touted idea of “data locality” which, in hindsight, was a big mismatch. Storage size tends to go only one way: up. At the same time, you want the compute to be as elastic as possible, utilizing as much or as little as you need right now. Marrying both was always quite clumsy, but fortunately, AWS got its act together over time, improved intra-datacenter network performance considerably, and finally sorted out strong consistency in S3 (oh, the pain, the workarounds!). That brought it in line with Google Cloud on these points, making the storage-compute decoupling viable on AWS as well.</span></p><p><span style="font-weight: 400;">That last note is important: the building blocks offered by a cloud provider may encourage a good architecture (or push you away from one).</span></p><h2><span style="font-weight: 400;">Don’t forget to create a dev wishlist</span></h2><p><span style="font-weight: 400;">This isn’t an article in the style of “Stop using X, just use Y.” I believe you can create a wildly successful product (or fail spectacularly) with any popular technology. The question I tend to focus on instead is: “What constructs do we need to make systems easier, faster, and cheaper?” Here’s my partial wishlist:</span></p><ul><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">I want to launch jobs with better isolation from each other – each getting the resources it needs to run unhindered, rather than needing to fight over resources from a very limited pool, avoiding any possible domino effect from a single job derailing.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">I want the needed resources to be (nearly) instantly available</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">I only want to pay for the actual work done, from the millisecond my actual code started running to the millisecond it ended.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">I want to push the complexity of orchestrating hardware and software to battle-tested components whose focus is exactly that rather than any applicative logic. Using these lower-level constructs, I could build higher-level orchestration that is way more straightforward. Simple (</span><a href="https://www.infoq.com/presentations/Simple-Made-Easy/" target="_blank" rel="noopener noreferrer"><span style="font-weight: 400;">rather than easy</span></a><span style="font-weight: 400;">) is robust.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">I want jobs to run in multiple modes: it could be “serverless” for fast, easy scaling of bursty short-lived work and interactive user requests at the expense of a higher price per compute unit/second. Or, it could be utilizing spot / preemptive instances — somewhat slower to launch and scale, but very cheap for scheduled bulk workloads.</span></li></ul><p><span style="font-weight: 400;">I’m not inventing any new concepts here. The building blocks are essentially readily available these days. The open-source software to take advantage of all these to the max, however, is not so available. To demonstrate what I mean, let’s tackle a real challenge guided by these principles. In part two of this series, I will dive into <a href="https://github.com/DynamicYieldProjects/funnel-rocket">Funnel Rocket</a>, an open-source query engine that is my attempt at building a solution. The goal was to build something to solve a very specific pain point we needed to address here, at Dynamic Yield, but over time, as we’ve spent more time working on it, I’ve come to realize how it can also become a testbed for so much more.</span> So now, <a href="https://www.dynamicyield.com/blog/funnel-rocket-serverless-query-engine">let’s move on to part two</a>.</p><p><img fetchpriority="high" decoding="async" class="wp-image-160195 alignnone" src="https://www.dynamicyield.com/wp-content/uploads/2021/07/funnel-rocket-inline-3.png" alt="funnel rocket" width="1048" height="524" /></p></div></article><div style="clear: both;"></div></div></div><div class="article-content"><div class="article-separator"><svg width="54" height="26" viewBox="0 0 54 26" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M53.0088 25.6367C52.7884 21.9564 51.8025 18.3625 50.1141 15.0849C48.4256 11.8073 46.0718 8.9181 43.2031 6.60203L43.2031 25.6367L53.0088 25.6367Z" fill="black"/> <path d="M14.4395 3.59038C10.3237 5.69174 6.82743 8.83082 4.29638 12.6973C1.76533 16.5638 0.28711 21.0239 0.0078125 25.6367L14.4395 25.6367L14.4395 3.59038Z" fill="black"/> <path d="M17.6563 2.20809L17.6562 25.6367L39.9829 25.6367L39.9829 4.36701C39.9829 4.36701 30.7303 -2.31342 17.6563 2.20809Z" fill="black"/> </svg></div><div class="article-tags-block"> <strong>Categories:</strong><ul class="post-categories"><li><a href="https://www.dynamicyield.com/blog/category/product/" rel="category tag">Product</a></li></ul></div><div class="article-tags-block"><strong>Tags:</strong><a href="https://www.dynamicyield.com/blog/tag/dy-labs/" rel="tag">DY Labs</a><a href="https://www.dynamicyield.com/blog/tag/engineering/" rel="tag">Engineering</a><a href="https://www.dynamicyield.com/blog/tag/rd/" rel="tag">R&D</a></div></div></div><section class="lc-subscription-section"><div class="lc-subscription-form-block lc-subscription-inner"><h4 class="lc-subscription-title">Sign up for the XP² newsletter</h4><div class="lc-subscription-text">Join thousands of readers from Target, Citi, Spotify, Hulu, Google, Sephora, and other innovative brands who read our bi-weekly XP² newsletter, delivering educational content, research, and insights straight to your inbox</div><form class="mktoForm" data-formId="3876" data-formInstance="sub-inline"></form><div class="lc-privacy-wrapper"><div class="lc-privacy"> You may unsubscribe at any time. Visit our <a href="/privacy-policy/">privacy policy</a> to learn more about how we process your data and your rights as a data subject.</div></div></div><div class="lc-subscription-ty-block lc-subscription-inner"><h4 class="lc-subscription-title text-center">Thanks for<br> signing up!</h4></div></section><div class="container"><div class="related-posts-wrapper"><div id="dc_crp_related" class="crp_related"><h3>YOU MIGHT ALSO LIKE</h3><ul><li><a href="https://www.dynamicyield.com/blog/funnel-rocket-serverless-query-engine/"><img src="https://www.dynamicyield.com/wp-content/uploads/2021/07/funnel-rocket-blog-2.png" alt="" class="crp_thumb"><div class="crp_title">From DY Labs: Introducing Funnel Rocket, an open-source serverless query engine</div><div class="crp_button button">READ MORE</div></a></li><li><a href="https://www.dynamicyield.com/blog/introducing-enhanced-facebook-remarketing-with-dynamic-yield/"><img src="https://www.dynamicyield.com/wp-content/uploads/2017/04/bed-laptop.jpg" alt="" class="crp_thumb"><div class="crp_title">Introducing: Enhanced Facebook Remarketing With Dynamic Yield</div><div class="crp_button button">READ MORE</div></a></li><li><a href="https://www.dynamicyield.com/blog/introducing-dynamic-yield-for-email/"><img src="https://www.dynamicyield.com/wp-content/uploads/2018/01/Email_post.jpg" alt="" class="crp_thumb"><div class="crp_title">Introducing: Dynamic Yield for Email</div><div class="crp_button button">READ MORE</div></a></li></ul></div></div></div><div class="et_pb_section post_slider_row test_posts_carousel select-clients-carousel et_section_regular"
style="background-color:#f9f9f9;"><div class="et_pb_row"><div class="et_pb_column et_pb_column_4_4"><div class="et_pb_text et_pb_bg_layout_light et_pb_text_align_left"><div class="case-studies-carousel-title">Driving Big Results with Personalization</div><div class="posts_carousel"><ul id="posts_carousel"><li class="243971"><a href="https://www.dynamicyield.com/case-studies/valamar/"><img class="b-lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://www.dynamicyield.com/wp-content/uploads/2026/02/mc-cm-valmar-excerpt-544x672-1.jpg" width="281" height="347" /></a><div class="grid_title">How Valamar converts travel intent into bookings with real-time context</div></li><li class="243414"><a href="https://www.dynamicyield.com/case-studies/saks-fifth-avenue/"><img class="b-lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://www.dynamicyield.com/wp-content/uploads/2025/11/mc-cm-saks-5thave-excerpt-544x672_v2.jpg" width="281" height="347" /></a><div class="grid_title">What makes Saks’ personalization engine a game-changer for driving 10% more conversions?</div></li><li class="242646"><a href="https://www.dynamicyield.com/case-studies/bergzeit/"><img class="b-lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://www.dynamicyield.com/wp-content/uploads/2025/09/mc-cm-bergzeit-excerpt-544x672-1.jpg" width="281" height="347" /></a><div class="grid_title">Bringing the in-store expert online: How Bergzeit reinvented gear discovery with conversational commerce</div></li><li class="237681"><a href="https://www.dynamicyield.com/case-studies/leroymerlin/"><img class="b-lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://www.dynamicyield.com/wp-content/uploads/2025/01/library-thumbnail.png" width="281" height="347" /></a><div class="grid_title">32% of Total Purchases from AdaptML Recommendations</div></li><li class="230927"><a href="https://www.dynamicyield.com/case-studies/signet/"><img class="b-lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://www.dynamicyield.com/wp-content/uploads/2024/10/signet-new-library-thumbnail.jpg" width="281" height="347" /></a><div class="grid_title">+88% Conversion Uplift with Mastercard Predictive Spend Insights</div></li><li class="224233"><a href="https://www.dynamicyield.com/case-studies/personalization-breeze/"><img class="b-lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://www.dynamicyield.com/wp-content/uploads/2024/07/library-thumbnail.png" width="281" height="347" /></a><div class="grid_title">Making Personalization a Breeze for Leading Financial Institutions</div></li><li class="221699"><a href="https://www.dynamicyield.com/case-studies/tui/"><img class="b-lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://www.dynamicyield.com/wp-content/uploads/2024/06/tui-library-thumbnail.png" width="281" height="347" /></a><div class="grid_title">+10.3% uplift in add-to-cart rate</div></li><li class="215474"><a href="https://www.dynamicyield.com/case-studies/sky/"><img class="b-lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://www.dynamicyield.com/wp-content/uploads/2024/02/library-thumbnail-2.png" width="281" height="347" /></a><div class="grid_title">39% decrease in same-month cancellations</div></li><li class="215658"><a href="https://www.dynamicyield.com/case-studies/electrolux/"><img class="b-lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://www.dynamicyield.com/wp-content/uploads/2024/02/library-thumbnail-1.png" width="281" height="347" /></a><div class="grid_title">16% contribution to D2C revenue from Dynamic Yield</div></li><li class="215340"><a href="https://www.dynamicyield.com/case-studies/on/"><img class="b-lazy" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://www.dynamicyield.com/wp-content/uploads/2024/02/library-thumbnail.png" width="281" height="347" /></a><div class="grid_title">16% of revenue from recommendations</div></li></ul></div><style>ul#posts_carousel:not(.slick-initialized) {
display: flex;
flex-direction: row;
overflow: visible;
width: 10000px;
}
.posts_carousel {
overflow-x: hidden;
}
#posts_carousel .slick-list {
max-width: 873px;
margin: auto;
left: 5px;
}
#posts_carousel li {
margin-right: 10px;
margin-bottom: 10px;
}
#posts_carousel li img{
box-shadow: 3px -1px 10px #C3C3C3;
}
#posts_carousel .slick-list:after {
content: '';
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 10px;
background: #f9f9f9;
}
#posts_carousel .slick-prev, #posts_carousel .slick-next {
width: 45px;
height: 45px;
}
#posts_carousel.slick-slider .slick-prev:before {
background: url('/wp-content/themes/Divi/images/arrow_left.svg')50% no-repeat;
opacity: 0.5;
width: 40px;
height: 40px;
}
#posts_carousel.slick-slider .slick-next:before {
background: url('/wp-content/themes/Divi/images/arrow_right.svg')50% no-repeat;
opacity: 0.5;
width: 40px;
height: 40px;
}
.post_slider_row {
overflow-x: hidden;
}
@media(max-width: 980px){
#posts_carousel {
max-width: 450px;
margin: auto;
}
#posts_carousel .slick-list {
width: 278px;
max-width: 95%;
margin: auto;
left: auto;
}
#posts_carousel li {
margin-right: 0;
}
#posts_carousel .slick-list:after {
display: none;
}
}
@media(max-width: 480px){
.posts_carousel{
display: inline;
}
#posts_carousel .slick-prev {
left: -25px;
z-index: 9;
}
#posts_carousel .slick-next {
right: -25px;
z-index: 9;
}
}
@media(max-width: 360px){
#posts_carousel.slick-slider .slick-next:before {
position: relative;
right: -10px;
}
#posts_carousel.slick-slider .slick-prev:before {
position:relative;
left: -5.5px;
}
}</style><script type="text/javascript">$=jQuery.noConflict();
$(".posts_carousel").css({visibility: "visible"});
$(window).load(function(){
$("#posts_carousel").slick({
centerMode: false,
waitForAnimate: false,
slidesToShow: 3,
arrows: true,
dots: false,
autoplaySpeed: 5,
draggable: true,
swipeToSlide: true,
responsive: [
{
breakpoint: 981,
settings: {
slidesToShow: 1
}
},
]
});
$(".slider-widget ul").css({opacity: "1"});
});
$("#posts_carousel").on("beforeChange", function(event, slick, currentSlide, nextSlide){
var imagesToLoad = $(".posts_carousel .b-lazy");
var slickCarouselBlazy = new Blazy();
slickCarouselBlazy.load(imagesToLoad);
});
let pageUrl = window.location.href;
let csCard = $(".posts_carousel a");
if(csCard) {
csCard.on("click", function(e) {
let ctaUrl = $(this).attr("href"),
ctaName = $(this).parent().find(".grid_title").text().trim();
adobeDataLayer.push({
"event": "tileClick",
"clickInfo": {
tileName: ctaName,
destinationURL: ctaUrl,
tileSection : "Posts Carousel",
tileLocation: pageUrl,
}
});
});
}</script> </div></div></div></div> <script type='text/javascript'>//DY.API('siteVar', {id: 128, value: 'Elad Rosenheim'});
//DY.API('siteVar', {id: 129, value: 'Product'});</script> <footer id="main-footer" class=""><div class="footer-top"><div class="footer-container"><h4>Make hyper-personalization a reality</h4><p>Transform simple customer transactions into enduring relationships and unlock a new horizon of growth</p><div class="footer-btns-wrap"> <a href="https://www.dynamicyield.com/request-demo/" class="btn-teal">Contact Sales</a> <a href="https://www.dynamicyield.com/product-demo/" class="btn-transparent">Watch a product demo<svg xmlns="http://www.w3.org/2000/svg" width="15.625" height="15.625" viewBox="0 0 15.625 15.625"> <path id="Icon_ionic-ios-play-circle" data-name="Icon ionic-ios-play-circle" d="M10.688,3.375A7.313,7.313,0,1,0,18,10.688,7.311,7.311,0,0,0,10.688,3.375Zm2.946,7.45L8.81,13.743a.156.156,0,0,1-.236-.137V7.77a.156.156,0,0,1,.236-.137l4.823,2.918A.161.161,0,0,1,13.634,10.825Z" transform="translate(-2.875 -2.875)" fill="none" stroke="rgba(0,0,0,0.8)" stroke-width="1"/> </svg> </a></div><ul class="footer-certificates"><li class="retina_parent"> <a href="https://www.dynamicyield.com/compliance/"> <img src="/wp-content/uploads/2022/05/gdpr-icon.png" alt="gdpr icon" width="139" height="70"> </a></li><li class="retina_parent"> <a href="https://www.dynamicyield.com/compliance/"> <img src="/wp-content/uploads/2023/04/SOCII-Badge.png" alt="socii icon" width="70" height="70"> </a></li><li> <a href="https://www.dynamicyield.com/compliance/"> <img src="/wp-content/uploads/2022/05/ccpa-icon.svg" alt="ccpa icon" width="117" height="40"> </a></li><li class="retina_parent"> <a href="https://www.dynamicyield.com/compliance/"> <img src="/wp-content/uploads/2022/05/iso-27001.png" alt="iso icon" width="106" height="68"> </a></li></ul></div></div><div class="footer-container"><div id="footer-widgets"><div class="footer-widget"><div id="nav_menu-2" class="fwidget et_pb_widget widget_nav_menu"><h4 class="title">Key Capabilities</h4><div class="menu-core-capabilities-container"><ul id="menu-core-capabilities" class="menu"><li id="menu-item-230872" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-230872"><a href="https://www.dynamicyield.com/segmentation/">Segmentation</a></li><li id="menu-item-5913" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-5913"><a href="https://www.dynamicyield.com/targeting/">Targeting</a></li><li id="menu-item-198647" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-198647"><a href="https://www.dynamicyield.com/recommendations/">Recommendations</a></li><li id="menu-item-198648" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-198648"><a href="https://www.dynamicyield.com/journey-orchestration/">Journey Orchestration</a></li><li id="menu-item-230873" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-230873"><a href="https://www.dynamicyield.com/optimization/">Optimization</a></li></ul></div></div></div><div class="footer-widget"><div id="nav_menu-13" class="fwidget et_pb_widget widget_nav_menu"><h4 class="title">Industries</h4><div class="menu-industries-container"><ul id="menu-industries" class="menu"><li id="menu-item-51518" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-51518"><a href="/ecommerce/">eCommerce</a></li><li id="menu-item-51520" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-51520"><a href="/financial-services/">Financial Services</a></li><li id="menu-item-224041" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-224041"><a href="/restaurants/">Restaurants</a></li><li id="menu-item-224042" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-224042"><a href="/grocery/">Grocery</a></li><li id="menu-item-51519" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-51519"><a href="/b2b-ecommerce/">B2B eCommerce</a></li><li id="menu-item-13777" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13777"><a href="https://www.dynamicyield.com/travel/">Travel</a></li><li id="menu-item-19895" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-19895"><a href="https://www.dynamicyield.com/gaming/">iGaming</a></li><li id="menu-item-13775" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13775"><a href="https://www.dynamicyield.com/media/">Media</a></li></ul></div></div></div><div class="footer-widget"><div id="nav_menu-11" class="fwidget et_pb_widget widget_nav_menu"><h4 class="title">Why Dynamic Yield</h4><div class="menu-why-dynamic-yield-container"><ul id="menu-why-dynamic-yield" class="menu"><li id="menu-item-51524" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-51524"><a href="/customer-success/">Industry-Leading Services</a></li><li id="menu-item-31658" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-31658"><a href="https://www.dynamicyield.com/clients/">Global Scale</a></li><li id="menu-item-13718" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13718"><a href="https://www.dynamicyield.com/case-studies/">Real Impact</a></li><li id="menu-item-224043" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-224043"><a href="/ai/">Personalization AI</a></li><li id="menu-item-224044" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-224044"><a href="/partners/">Rich Partner Network</a></li><li id="menu-item-224045" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-224045"><a href="/enterprise-grade-personalization/">Enterprise-Grade Security</a></li></ul></div></div></div><div class="footer-widget"><div id="nav_menu-5" class="fwidget et_pb_widget widget_nav_menu"><h4 class="title">Company</h4><div class="menu-company-container"><ul id="menu-company" class="menu"><li id="menu-item-242875" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-242875"><a href="https://www.mastercard.com/us/en/for-the-world/about-us.html">About Us</a></li><li id="menu-item-19360" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-19360"><a href="https://events.dynamicyield.com/">Events</a></li><li id="menu-item-242874" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-242874"><a href="https://www.mastercard.com/us/en/news-and-trends/stories.html">Press</a></li><li id="menu-item-130411" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-130411"><a href="https://www.dynamicyield.com/blog/">Blog</a></li><li id="menu-item-226" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-226"><a href="https://www.dynamicyield.com/contact/">Contact</a></li><li id="menu-item-198646" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-198646"><a href="https://www.dynamicyield.com/partner-program/">Become a Partner</a></li><li id="menu-item-11264" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-11264"><a href="/request-demo/">Request Demo</a></li></ul></div></div><div id="text-6" class="fwidget et_pb_widget widget_text"><div class="textwidget"><ul style="min-width: 150px; margin-top: -15px;"><li><a style="color: #fff; font-weight: 500;" href="/careers/">We’re hiring!</a></li></ul></div></div></div><div class="lc-footer-nav-block"><div class="lc-footer-nav-header"> <a href="https://www.dynamicyield.com/learn/" class="lc-footer-logo"></a> <span>Take your knowledge to exponential levels</span></div><div class="lc-footer-menu"><ul id="menu-lc-menu-footer" class="menu"><li id="menu-item-212992" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-212992"><a href="https://www.dynamicyield.com/articles/">Articles</a></li><li id="menu-item-212993" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-212993"><a href="https://www.dynamicyield.com/learning-paths/">Learning Paths</a></li><li id="menu-item-212994" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-212994"><a href="https://www.dynamicyield.com/rooted-personalization/">Rooted Personalization</a></li><li id="menu-item-212995" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-212995"><a href="https://www.dynamicyield.com/personalization-examples/">Personalization Examples</a></li><li id="menu-item-212996" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-212996"><a href="https://www.dynamicyield.com/guides/">Guides</a></li><li id="menu-item-212997" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-212997"><a href="https://www.dynamicyield.com/talks/">Talks</a></li><li id="menu-item-212999" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-212999"><a href="https://www.dynamicyield.com/glossary-terms/">Encyclopedia</a></li><li id="menu-item-212998" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-212998"><a href="https://marketing.dynamicyield.com/benchmarks/">Benchmarks</a></li></ul></div></div></div></div><div id="et-footer-nav"><div class="footer-container"><ul id="menu-footer-menu" class="bottom-nav"><li id="menu-item-19183" class="footer_menu_title menu-item menu-item-type-custom menu-item-object-custom menu-item-19183"><a>Recommended Guides:</a></li><li id="menu-item-211968" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-211968"><a href="https://www.dynamicyield.com/article/personalization-guide/">Personalization</a></li><li id="menu-item-138198" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-138198"><a href="https://www.dynamicyield.com/lesson/introduction-to-ab-testing/">A/B Testing</a></li><li id="menu-item-147897" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-147897"><a href="https://www.dynamicyield.com/lesson/cro-plan/">Conversion Rate Optimization</a></li><li id="menu-item-19184" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-19184"><a href="/lesson/shopping-cart-abandonment-strategy/">Shopping Cart Abandonment</a></li><li id="menu-item-19185" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-19185"><a href="/lesson/product-recommendations-guide/">Product Recommendations</a></li><li id="menu-item-22805" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-22805"><a href="/lesson/promise-and-pitfalls-omnichannel-retailing/">Omnichannel Retailing</a></li><li id="menu-item-22885" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-22885"><a href="/lesson/the-economics-of-ecommerce-conversion-optimization/">eCommerce Conversion Rate Optimization</a></li><li id="menu-item-28240" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-28240"><a href="/article/50-most-important-dynamicyield-personalization-stats/">Personalization Statistics</a></li><li id="menu-item-33877" class="menu-item menu-item-type-post_type menu-item-object-post menu-item-33877"><a href="https://www.dynamicyield.com/article/tj-maxx-spired-checkout-optimization/">Checkout Optimization</a></li><li id="menu-item-123711" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-123711"><a href="/article/ecommerce-personalization-must-haves/">eCommerce Personalization</a></li><li id="menu-item-144090" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-144090"><a href="https://www.dynamicyield.com/lesson/strategizing-omnichannel-personalization/">Omnichannel Personalization</a></li><li id="menu-item-148146" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-148146"><a href="https://marketing.dynamicyield.com/benchmarks/cart-abandonment-rate/">Shopping Cart Abandonment Rate</a></li></ul><div class="footer-mach-logo retina_parent"> <img src="/wp-content/uploads/2022/05/mach-cert-22-wh.png" alt="Mach logo" width="63" height="70"></div><div class="language-switcher footer-language-switcher"><ul><li>en<ul><li><a class="active" href="https://www.dynamicyield.com/blog/dy-labs-building-blocks-open-source/">English</a></li><li><a href="https://www.dynamicyield.com/es/">Español</a></li><li><a href="https://www.dynamicyield.com/de/">Deutsch</a></li><li><a href="https://www.dynamicyield.com/fr/">Français</a></li><li><a href="https://www.dynamicyield.com/ja/">日本語</a></li></ul></li></li></ul></div></div></div><div id="footer-bottom"><div class="footer-container"><div class="footer_info_wrapper"><div id="footer-info"> <button id="ot-sdk-btn" class="ot-sdk-show-settings">Manage Cookies</button> <a href="/privacy-notice/" target="_blank" class="animlink">Privacy Notice</a> <a href="/tos/" target="_blank" class="animlink">Terms of use</a> <span>© 2026 Mastercard Dynamic Yield</span></div></div><div class="footer_social_icons"><style>.et-social-icons .et-social-icon img {
max-width: 16px;
transition: 0.2s all;
}
.et-social-icons .et-social-icon img:not(:hover) {
opacity: 0.5;
}</style><span itemscope itemtype="http://schema.org/Organization"><link itemprop="url" href="https://www.dynamicyield.com"><ul class="et-social-icons"><li class="et-social-icon"> <a itemprop="sameAs" href="https://www.linkedin.com/company/dynamic-yield" class="icon" target="_blank"> <img src="https://www.dynamicyield.com/wp-content/uploads/2025/09/Frame-5.png" alt="LinkedIn Logo" /> </a></li><li class="et-social-icon"> <a itemprop="sameAs" href="https://www.instagram.com/dynamicyield/" class="icon" target="_blank"> <img src="https://www.dynamicyield.com/wp-content/uploads/2025/09/Frame-4.png" alt="Instagram Logo" /> </a></li><li class="et-social-icon"> <a itemprop="sameAs" href="https://www.youtube.com/c/Dynamicyield" class="icon" target="_blank"> <img src="https://www.dynamicyield.com/wp-content/uploads/2025/09/Frame-3.png" alt="Youtube Logo" /> </a></li><li class="et-social-icon"> <a itemprop="sameAs" href="https://www.tiktok.com/@dynamic.yield" class="icon" target="_blank"> <img src="https://www.dynamicyield.com/wp-content/uploads/2025/09/Frame-2.png" alt="TikTok Logo" /> </a></li><li class="et-social-icon"> <a itemprop="sameAs" href="https://www.facebook.com/DynamicYield" class="icon" target="_blank"> <img src="https://www.dynamicyield.com/wp-content/uploads/2025/09/Frame-1.png" alt="Facebook Logo" /> </a></li><li class="et-social-icon"> <a itemprop="sameAs" href="https://twitter.com/DynamicYield" class="icon" target="_blank"> <img src="https://www.dynamicyield.com/wp-content/uploads/2025/09/Frame.png" alt="X Logo" /> </a></li></ul> </span></div></div></div></footer></div></div><div id="mobile_menu_overlay"></div> <script type="text/javascript">window.DY = window.DY || {};
DY.recommendationContext = { type: "POST", data: ['160194'], lng: "en_US" };</script> <script type='text/javascript' src='//cdn.dynamicyield.com/api/8765281/api_dynamic.js'></script> <script type='text/javascript' src='//cdn.dynamicyield.com/api/8765281/api_static.js'></script> <script type="text/javascript">var sbiajaxurl = "https://www.dynamicyield.com/wp-admin/admin-ajax.php";</script> <script type="text/javascript">!function(e,n){var r={"selectors":{"block":"pre.EnlighterJSRAW","inline":"code.EnlighterJSRAW"},"options":{"indent":2,"ampersandCleanup":true,"linehover":true,"rawcodeDbclick":false,"textOverflow":"break","linenumbers":true,"theme":"beyond","language":"generic","retainCssClasses":false,"collapse":false,"toolbarOuter":"","toolbarTop":"{BTN_RAW}{BTN_COPY}{BTN_WINDOW}{BTN_WEBSITE}","toolbarBottom":""},"resources":["https:\/\/www.dynamicyield.com\/wp-content\/plugins\/enlighter\/cache\/enlighterjs.min.css?tvrakvcLArVio6C","https:\/\/www.dynamicyield.com\/wp-content\/plugins\/enlighter\/resources\/enlighterjs\/enlighterjs.min.js"]},o=document.getElementsByTagName("head")[0],t=n&&(n.error||n.log)||function(){};e.EnlighterJSINIT=function(){!function(e,n){var r=0,l=null;function c(o){l=o,++r==e.length&&(!0,n(l))}e.forEach(function(e){switch(e.match(/\.([a-z]+)(?:[#?].*)?$/)[1]){case"js":var n=document.createElement("script");n.onload=function(){c(null)},n.onerror=c,n.src=e,n.async=!0,o.appendChild(n);break;case"css":var r=document.createElement("link");r.onload=function(){c(null)},r.onerror=c,r.rel="stylesheet",r.type="text/css",r.href=e,r.media="all",o.appendChild(r);break;default:t("Error: invalid file extension",e)}})}(r.resources,function(e){e?t("Error: failed to dynamically load EnlighterJS resources!",e):"undefined"!=typeof EnlighterJS?EnlighterJS.init(r.selectors.block,r.selectors.inline,r.options):t("Error: EnlighterJS resources not loaded yet!")})},(document.querySelector(r.selectors.block)||document.querySelector(r.selectors.inline))&&e.EnlighterJSINIT()}(window,console);</script><script type="text/javascript" id="rfw-script-js-extra">var rfw = {"speed":""};</script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_a5ec58aa1f222bedaf60cdced3b8a004.js?ver=2026020735" id="rfw-script-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_c1b7fbe6b1a3b777fddfe187094deb97.js?ver=2026020735" id="rfw-script-fitvid-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-includes/js/comment-reply.min.js?ver=935c7f8ce03960b02800bc8ae3231df8" id="comment-reply-js" async="async" data-wp-strategy="async"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_ea3fad8947382ebf8709507a11a805db.js" id="divi-fitvids-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/themes/Divi/js/waypoints.min.js" id="waypoints-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_845779ea879c70773af95b2f6fc394d2.js" id="magnific-popup-js"></script> <script type="text/javascript" id="divi-custom-script-js-extra">var et_custom = {"ajaxurl":"https:\/\/www.dynamicyield.com\/wp-admin\/admin-ajax.php","images_uri":"https:\/\/www.dynamicyield.com\/wp-content\/themes\/Divi\/images","et_load_nonce":"b06e7d0c21","subscription_failed":"Please, check the fields below to make sure you entered the correct information.","fill":"Fill","field":"field","invalid":"Invalid email","captcha":"Captcha"};</script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_43b4a88b2828bc5c023dc913689e8da5.js?ver=20.4" id="divi-custom-script-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/themes/Divi/custom/bootstrap/js/bootstrap.min.js" id="bootstrap-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/themes/Divi/custom/slick/slick.min.js" id="slick-js"></script> <script type="text/javascript" data-ot-ignore src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_12efd5a7d441d8b7f817fc6fc685dca9.js?ver=21.85" id="customscript-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_33fa37a5effe9361e40b8525e36e3eaf.js" id="typed-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_eb8981568f49ac148e96af3241eb95c7.js?ver=21.85" id="form_validation-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_be33bce741fd746dee1a6cf31c0b5bde.js" id="retina_js-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_9a50928b26148d1c35a95957e5ef2b9d.js?ver=21.85" id="mkto-scripts-js"></script> <script type="module" src="https://www.dynamicyield.com/wp-content/themes/Divi/js/cid-validation.js?ver=21.85" id="cid-validation"></script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.min.js" id="select2-js-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_6ee6e48031ef5dddfe05a9f11136201f.js" id="post-checklist-js-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_5113be2479418a077e699b1647e0adef.js" id="post-event-cards-js-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/plugins/wp-featherlight/js/wpFeatherlight.pkgd.min.js?ver=1.3.4" id="wp-featherlight-js"></script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_17babe2fc54117766e24bd50889c6577.js?ver=1772307322" id="article-script-js"></script> <script type="text/javascript" id="dc_conversion_api-js-extra">var ajax_obj = {"nonce":"4a0670c385","ajax_url":"https:\/\/www.dynamicyield.com\/wp-admin\/admin-ajax.php","ajax_action":"conversion_api_call"};</script> <script type="text/javascript" src="https://www.dynamicyield.com/wp-content/cache/autoptimize/js/autoptimize_single_34a6a3100a2ecbc7706af2d4c798f856.js?ver=935c7f8ce03960b02800bc8ae3231df8" id="dc_conversion_api-js"></script> <script type="text/javascript" data-noptimize>var dy_search_params = new URLSearchParams(window.location.search);
if(dy_search_params.has('utm_source')) {
localStorage.setItem('utm_source', dy_search_params.get('utm_source'));
}
if(dy_search_params.has('utm_medium')) {
localStorage.setItem('utm_medium', dy_search_params.get('utm_medium'));
}
if(dy_search_params.has('utm_content')) {
localStorage.setItem('utm_content', dy_search_params.get('utm_content'));
}
if(dy_search_params.has('utm_campaign')) {
localStorage.setItem('utm_campaign', dy_search_params.get('utm_campaign'));
}
if(dy_search_params.has('utm_term')) {
localStorage.setItem('utm_term', dy_search_params.get('utm_term'));
}
if(dy_search_params.has('mkt_tok')) {
localStorage.setItem('mkt_tok', dy_search_params.get('mkt_tok'));
}
// Also, fill in the data inside the Marketo form once its available
if(typeof window.MktoForms2 === 'object') {
MktoForms2.whenReady(function(_form) {
var form = _form.getFormElem();
console.log('MKTO FORM READY');
// Append the mkt_tok param if it exists in the URL
var ls_mkto_tok = localStorage.getItem('mkt_tok');
if(ls_mkto_tok) {
_form.addHiddenFields({
mkt_tok: ls_mkto_tok
});
_form.vals({ mkt_tok: ls_mkto_tok });
}
// Fill in the UTM data from localStorage
var dy_utms = {
'utm_source': 'txt_source__c',
'utm_medium': 'txt_medium__c',
'utm_content': 'txt_content__c',
'utm_campaign': 'txt_campaign_name__c',
'utm_term': 'txt_term__c',
'gclid': ['GCLID__c', 'GCLID_c__c']
};
for(var i = 0; i < Object.keys(dy_utms).length; i++) {
var ls_key = Object.keys(dy_utms)[i],
ls_value = localStorage.getItem(ls_key),
form_key = dy_utms[ls_key],
form_field;
if(ls_value) {
if(ls_key === 'gclid') {
ls_value = JSON.parse(ls_value).value;
}
if(typeof(form_key) === 'string') {
form_field = form[0].querySelector('input[type="hidden"][name="' + form_key + '"]');
if(form_field) {
form_field.value = ls_value;
}
} else {
for(var j = 0; j < form_key.length; j++) {
form_field = form[0].querySelector('input[type="hidden"][name="' + form_key[j] + '"]');
if(form_field) {
form_field.value = ls_value;
}
}
}
}
}
// IP Address
fetch('https://www.cloudflare.com/cdn-cgi/trace').then(function(result) {
result.text().then(function(values) {
values.split("\n").map(function(item) {
var pair = item.split('=');
if(['ip'].includes(pair[0])) {
form[0].querySelector('input[type="hidden"][name="IP__c"]').value = pair[1];
}
});
});
});
// GA ID and Referrer
var dy_utms_cookie = {};
document.cookie.split(';').forEach(function(el) {
var splitCookie = el.split('=');
var key = splitCookie[0].trim();
var value = splitCookie[1];
dy_utms_cookie[key] = value;
});
if(dy_utms_cookie["_ga"]) {
form[0].querySelector('input[type="hidden"][name="Visitor_ID__c"]').value = dy_utms_cookie["_ga"].substring(6);
}
if(dy_utms_cookie["personalize_referrer_string"]) {
form[0].querySelector('input[type="hidden"][name="Referral__c"]').value = dy_utms_cookie["personalize_referrer_string"].substring(6);
}
// ZoomInfo
if(localStorage.getItem('ZoomInfoData')) {
var zoominfo_data = JSON.parse(localStorage.getItem('ZoomInfoData'));
if(zoominfo_data) {
form[0].querySelector('input[type="hidden"][name="Alexa_Rank__c"]').value = zoominfo_data.alexaglobalrank;
form[0].querySelector('input[type="hidden"][name="Employees__c"]').value = zoominfo_data.employeesrange;
form[0].querySelector('input[type="hidden"][name="Company_Revenue_Range__c"]').value = zoominfo_data.estimatedannualrevenue;
}
}
// Also, dispatch a dataLayer event on success
_form.onSuccess(function(values, follow_up_url) {
window.dataLayer = window.dataLayer || [];
if([3739, 4802, 5094, 5110, 4946, 5076, 5116, 5171, 5172, 5173].includes(_form.getId())) {
window.dataLayer.push({
'event': 'demo_request_complete',
'eventCallback': function() {
if(follow_up_url) {
window.location.href = follow_up_url;
}
}
});
return false;
} else if([3876].includes(_form.getId())) {
window.dataLayer.push({
'event': 'newsletter_signup_complete',
'eventCallback': function() {
if(follow_up_url) {
window.location.href = follow_up_url;
}
}
});
return false;
}
});
});
}</script> <script>if(typeof(jQuery) !== 'undefined') {
$ = jQuery.noConflict();
}
function getUrlParameter(sParam) {
var sPageURL = decodeURIComponent(window.location.search.substring(1)),
sURLVariables = sPageURL.split('&'),
sParameterName,
i;
for (i = 0; i < sURLVariables.length; i++) {
sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] === sParam) {
return sParameterName[1] === undefined ? true : sParameterName[1];
}
}
}
$(window).load(function(){
var videoID = getUrlParameter('video');
if(videoID !== undefined){
if($('#wistia-' + videoID + '-1').length){
var videoName = $('#wistia-' + videoID + '-1').parents('.tab-pane');
videoName = videoName[0].id
}
if($('a[href="#' + videoName +'"]').length){
$('a[href="#' + videoName +'"]').each(function(){
$(this).click();
});
}
addScript('https://fast.wistia.com/embed/medias/'+ videoID +'.jsonp');
addScript('https://fast.wistia.com/assets/external/E-v1.js');
$('body').append('<span class="wistia_embed wistia_async_'+videoID+' popover=true popoverContent=link dy-wistia-popup" style="display:inline"></span>');
window._wq = window._wq || [];
_wq.push({ id: videoID, onReady: function(video) {
var video = Wistia.api(videoID);
video.popover.show(); // open the popover
video.play(); // play the video
setTimeout(function(){video.unmute();}, 500);
}});
}
});</script> <style>#adBanner {
background-color: transparent;
height: 0;
width: 1px;
}</style><div id="wrapfabtest"><div id="adBanner"></div></div></body></html>