A Developer’s Guide to Database Sharding With MongoDB

As a developer, you may encounter situations where your application's database must handle large amounts of data. One way to manage this data effectively is through database sharding, a technique that distributes data across multiple servers or databases horizontally. Sharding can improve performance, scalability, and reliability by breaking up a large database into smaller, more manageable pieces called shards.

In this article, we'll explore the concept of database sharding, discuss various sharding strategies, and provide a step-by-step guide to implementing sharding in MongoDB, a popular NoSQL database.

Why Do We Need Databases and SQL?

SQL has a long and proven history. It has survived the fuss around NoSQL. Even if it is not perfect, it has been demonstrated to be the best available language for data. This is no surprise! The story began in the 1960s with the development of databases—an era marked by the introduction of the Integrated Data Store (IDS) at General Electric. However, it was Edgar Codd’s relational model that revolutionized data handling. His model, which turned data into a series of tables (or, more strictly, relations), has influenced database systems ever since. This era also saw the birth of SQL (Structured Query Language), which became the standard language for interacting with relational databases, including MariaDB and others.

The Utility of Relational Database Systems

So, why do we need all this database stuff? Let’s imagine you’re building an app, maybe a simple to-do list to keep track of your daily tasks. Initially, you might think, “Why not just save each task directly to a file?” After all, my programming language has constructs and libraries to save and read data from disk. Also, implementing this seems straightforward: create a task, write it to a file, delete a task, and remove it from the file. These are good points; however, as your app gains traction, users start to aggregate, and suddenly, you have thousands of users trying to add, delete, and modify tasks simultaneously. At this point, the simplicity of files becomes fragile. Imagine one user is updating a task at the exact moment another tries to delete it. Or maybe two users are editing the same task at the same time. With a simple file system, you’re likely to end up with corrupted or lost data because there’s no inherent mechanism to handle such conflicts.

Performing Advanced Facebook Event Data Analysis With a Vector Database

In today's digital age, professionals across all industries must stay updated with upcoming events, conferences, and workshops. However, efficiently finding events that align with one's interests amidst the vast ocean of online information presents a significant challenge.

This blog introduces an innovative solution to this challenge: a comprehensive application designed to scrape event data from Facebook and analyze the scraped data using MyScale. While MyScale is commonly associated with the RAG tech stack or used as a vector database, its capabilities extend beyond these realms. We will utilize it for data analysis, leveraging its vector search functionality to analyze events that are semantically similar, thus providing better results and insights.

What’s a Resume For?

In the course of talking about job hunting with friends, colleagues, and randos on Slack and elsewhere, I end up talking about resumes. A lot. There is, (in my (not so) humble) opinion, a sizeable misunderstanding about what resumes are, what they do, how they should look, the effort one should (or shouldn’t) put into creating them, and more.

Given the current period of churn in the tech industry and the resulting uptick in the frequency with which I’m having these types of conversations, I decided to commit to what’s become a standard part of my “so you’re looking for a new job?” shpiel to paper (or at least electrons).

Why GraphQL Is a Superior Choice for Building Microservices?

In the evolving landscape of software development, the debate between using REST and GraphQL for building microservices is becoming increasingly relevant. Both technologies have their proponents and critics, but when it comes to the specific needs of microservices architectures, GraphQL emerges as the clear front-runner. Here's why.

Understanding the RESTful Concerns

Popularity vs. Limitations

While REST has been the go-to API style for many years, lauded for its simplicity and general applicability, its limitations become glaringly apparent in the context of microservices. These limitations include:

Finite State Machines: How to Enhance Software Testing

Ensuring application reliability is a never-ending quest. Finite state machines (FSMs) offer a solution by modeling system behavior as states and transitions, a useful tool that can help software engineers understand software behavior and design effective test cases. 

This article explores the pros and cons of FSMs via simple examples. We will also make a short comparison between the usefulness and applicability of FSMs and program graphs in software testing.

The State of Observability 2024: Navigating Complexity With AI-Driven Insights

In today's fast-paced digital landscape, organizations are increasingly embracing multi-cloud environments and cloud-native architectures to drive innovation and deliver seamless customer experiences. However, the 2024 State of Observability report from Dynatrace reveals that the explosion of data generated by these complex ecosystems is pushing traditional monitoring and analytics approaches to their limits.

The research, which surveyed 1,300 CIOs and technology leaders from large organizations worldwide, highlights the pressing need for a mature AI, analytics, and automation strategy to overcome the challenges posed by modern cloud environments. As Andi Grabner, Dynatrace DevOps Activist, aptly puts it, "'Multicloud environments' and 'cloud-native architectures' are not just buzzwords; they are the reality of today's complex and dynamic IT landscape. They enable developers, engineers, and architects to drive innovation, but they also introduce new challenges."

How To Improve Your DevOps Workflow

There is no better architecture than DevOps Architecture. Is there? Well, there is no doubt that incorporating the DevOps Architecture Diagram into your software development projects will accelerate and improve processes. 

Just like that, following the right practices and principles can enhance your DevOps workflow and transform your organization’s mindset and collaboration models.

Python in Urban Planning

Our thinking of software is often limited and full of basic assumptions and stereotypes — for most of us, it’s a section of computer science and more so just programming languages and related mathematical issues. However, with the rapid development of the software industry and the digital revolution, more and more spheres of our lives become interconnected with software in non-obvious ways. This article explores the role of Python in urban planning, highlighting its importance in leveraging data analysis and programming for sustainable city development.

As our cities undergo rapid expansion, it becomes crucial to find new tools for building convenient, sustainable, and efficient spaces. The concept of smart cities was created to include all those aspects and find solutions using cutting-edge technology. Modern cities should become hubs for economic growth, a place to nurture creativity and facilitate innovation. Creating a unique place that would be both efficient and convenient for its inhabitants is a major challenge for city planners and policymakers. They should take into account the vastness of complications, such as congested roads, polluted air, limited water resources, and ineffective waste management, that plague urban landscapes. The best way to achieve that is to merge physical and digital systems using tools like data analysis, sensors, and interconnected devices. 

Introduction to Modern Data Stack

The modern data stack represents the evolution of data management, shifting from traditional, monolithic systems to agile, cloud-based architectures. It's designed to handle large amounts of data, providing scalability, flexibility, and real-time processing capabilities. This stack is modular, allowing organizations to use specialized tools for each function: data ingestion, storage, transformation, and analysis, facilitating a more efficient and democratized approach to data analytics and business operations. As businesses continue to prioritize data-driven decision-making, the modern data stack has become integral to unlocking actionable insights and fostering innovation.

The Evolution of Modern Data Stack

The Early Days: Pre-2000s

Companies use big, single systems to keep and manage their data. These were good for everyday business tasks but not so much for analyzing lots of data. Data was stored in traditional relational databases like Oracle, IBM DB2, and Microsoft SQL Server.

Success At Scale: Last Chance For Pre-Sale Price

We love practical books that focus on failures and success stories. And we’ve finally sent our latest book, Addy Osmani’s Success at Scale is at the printer. That means you’ll soon have another wonderful, practical book in your hands. It also means the price of the book is about to go up. So pre-order your copy now to save on the cover price by the 11th of March, 2024!

## Reviews And Testimonials
“This book reveals in its pages the collective wisdom of frontend engineers working on global web projects. It’s the perfect way to enhance your web applications’ potential by optimizing performance with practical tips straight from the trenches.”

Luca Mezzalira, Principal Serverless Specialist Solutions Architect at Amazon Web Services (AWS) and O’Reilly author
Success at Scale, masterfully curated by Addy Osmani, serves as an invaluable compass for the aspiring developers navigating the complex waters of web development. It’s more than a book; it’s a transmission of wisdom, guiding junior developers towards the shores of big tech companies. With its in-depth case studies and focus on performance, capabilities, accessibility, and developer experience, it prepares the next generation of tech talent to not just participate in, but to shape the future of digital innovation.”

Jerome Hardaway, Engineering AI products at Microsoft
## Contents

Success at Scale is a curated collection of best-practice case studies capturing how production sites of different sizes tackle performance, accessibility, capabilities, and developer experience at scale. Case studies are from industry experts from teams at Instagram, Shopify, Netflix, eBay, Figma, Spotify, Wix, Lyft, LinkedIn, and many more. Guidance that stands the test of time.

Join Addy Osmani, your curator, as we dive into a nuanced look at several key topics that will teach you tips and tricks that may help you optimize your own sites. The book also includes short interviews with contributors on what additional lessons, challenges, and tips they have to share some time after the case studies were written.

  • Performance includes examples of measuring, budgeting, optimizing, and monitoring performance, in addition to tips for building a performance culture.
  • Capabilities is about bridging the gap between native capabilities and the modern web. You’ll explore web apps, native apps, and progressive web applications.
  • Accessibility makes web apps viable for diverse users, including people with temporary or permanent disabilities. Most of us will have a disability at some point in our lives, and these case studies show how we can make the web work for all of us.
  • Developer Experience is about building a project environment and culture that encourage support, growth, and problem-solving within teams. Strong teams build great projects!
We’re Trying Out Something New

In an effort to conserve resources here at Smashing, we’re trying something new with Success at Scale. The printed book will be 304 pages, and we’ll make an expanded PDF version available to everyone who purchases a print book. This accomplishes a few good things:

  • We will use less paper and materials because we are making a smaller printed book;
  • We’ll use fewer resources in general to print, ship, and store the books, leading to a smaller carbon footprint; and
  • Keeping the book at more manageable size means we can continue to offer free shipping on all Smashing orders!

Smashing Books have always been printed with materials from FSC Certified forests. We are committed to finding new ways to conserve resources while still bringing you the best possible reading experience.

About the Author

Addy Osmani is an engineering leader working on Google Chrome. He leads up Chrome’s Developer Experience organization, helping reduce the friction for developers to build great user experiences.

Technical Details
  • ISBN: 978-3-910835-00-9 (print)
  • Quality hardcover, 304 pages, stitched binding, ribbon page marker.
  • Free worldwide airmail shipping from Germany mid March 2024.
  • eBook available for download as PDF, ePUB, and Amazon Kindle.
  • Pre-order the book.
Community Matters ❤️

Producing a book takes quite a bit of time, and we couldn’t pull it off without the support of our wonderful community. A huge shout-out to Smashing Members for the kind, ongoing support. The eBook is and always will be free for Smashing Members. Plus, Members get a friendly discount when purchasing their printed copy. Just sayin’! ;-)

More Smashing Books & Goodies

Promoting best practices and providing you with practical tips to master your daily coding and design challenges has always been (and will be) at the core of everything we do at Smashing.

In the past few years, we were very lucky to have worked together with some talented, caring people from the web community to publish their wealth of experience as printed books that stand the test of time. Heather and Steven are two of these people. Have you checked out their books already?

Understanding Privacy

Everything you need to know to put your users first and make a better web.

Add to cart $44

Touch Design for Mobile Interfaces

Learn how touchscreen devices really work — and how people really use them.

Add to cart $44

Interface Design Checklists

100 practical cards for common interface design challenges.

Add to cart $39

Microservices: Avoiding the Pitfalls, Embracing the Potential: A Guide to Anti-Patterns

Microservices have transformed the software development environment, offering more agility, scalability, and resilience. However, negotiating this architectural transition is not without obstacles. Falling victim to common anti-patterns can turn your microservices utopia into a tangled web of complexity and aggravation.

Fear not, intrepid developer! This article teaches you how to avoid these mistakes and realize the full potential of microservices. So, put on your anti-pattern-fighting cape and join us on this exploration:

How a Distributed File System in Go Reduced Memory Usage by 90%

JuiceFS, written in Go, can manage tens of billions of files in a single namespace. Its metadata engine uses an all-in-memory approach and achieves remarkable memory optimization, handling 300 million files with 30 GiB of memory and 100 microseconds response time. Techniques like memory pools, manual memory management, directory compression, and compact file formats reduced metadata memory usage by 90%.

JuiceFS Enterprise Edition, a cloud-native distributed file system written in Go, can manage tens of billions of files in a single namespace. After years of iteration, it can manage about 300 million files with a single metadata service process using 30 GiB of memory while maintaining the average processing time of metadata requests at 100 microseconds. In production, 10 metadata nodes, each with 512 GB of memory, collectively manage over 20 billion files.

Modern CSS Tooltips And Speech Bubbles (Part 2)

I hope you were able to spend time getting familiar with the techniques we used to create tooltips in Part 1 of this quick two-parter. Together, we were able to create a flexible tooltip pattern that supports different directions, positioning, and coloration without adding any complexity whatsoever to the HTML.

We leveraged the CSS border-image property based on another article I wrote while applying clever clip-path tricks to control the tooltip’s tail. If you haven’t checked out that article or the first part of this series, please do because we’re jumping straight into things today, and the context will be helpful.

So far, we’ve looked at tooltip shapes with triangular tails with the option to have rounded corners and gradient coloration. Sure, we were able to do lots of things but there are many other — and more interesting — shapes we can accomplish. That’s what we’re doing in this article. We will handle cases where a tooltip may have a border and different tail shapes, still with the least amount of markup and most amount of flexibility.

Before we start, I want to remind you that I’ve created a big collection of 100 tooltip shapes. I said in Part 1 that we would accomplish all of them in these two articles. We covered about half of them in Part 1, so let’s wrap things up here in Part 2.

The HTML

Same as before!

<div class="tooltip">Your text content goes here</div>

That’s the beauty of what we’re making: We can create many, many different tooltips out of the same single HTML element without changing a thing.

Tooltips With Borders

Adding a border to the tooltips we made in Part 1 is tricky. We need the border to wrap around both the main element and the tail in a continuous fashion so that the combined shape is seamless. Let’s start with the first simple shape we created in Part 1 using only two CSS properties:

.tooltip {
  /* tail dimensions */
  --b: 2em; /* base */
  --h: 1em; /* height*/

  /* tail position */
  --p: 50%;

  border-image: fill 0 // var(--h)
    conic-gradient(#CC333F 0 0);
  clip-path: 
    polygon(0 100%, 0 0,100% 0, 100% 100%,
      min(100%, var(--p) + var(--b) / 2) 100%,
      var(--p) calc(100% + var(--h)),
      max(0%, var(--p) - var(--b) / 2) 100%);
}

Here’s the demo. You can use the range slider to see how flexible it is to change the tail position by updating the --p variable.

This probably is not that a big deal in most cases. A few pixels aren’t a glaring visual issue, but you can decide whether or not it meets your needs. Me? I’m a perfectionist, so let’s try to fix this minor detail even if the code will get a little more complex.

We need to do some math that requires trigonometric functions. Specifically, we need to change some of the variables because we cannot get what we want with the current setup. Instead of using the base variable for the tail’s dimensions, I will consider an angle. The second variable that controls the height will remain unchanged.

The relationship between the base (--b) and the angle (--a) is equal to B = 2*H*tan(A/2). We can use this to update our existing code:

.tooltip {
  /* tail dimensions */
  --a: 90deg; /* angle */
  --h: 1em; /* height */

  --p: 50%; /* position */
  --t: 5px; /* border thickness */

  border-image: fill 0 // var(--h)
    conic-gradient(#5e412f 0 0); /* the border color */
  clip-path: 
    polygon(0 100%, 0 0, 100% 0, 100% 100%,
      min(100%, var(--p) + var(--h) * tan(var(--a) / 2)) 100%,
      var(--p) calc(100% + var(--h)),
      max(0%, var(--p) - var(--h) * tan(var(--a) / 2)) 100%);
  position: relative;
  z-index: 0;
}
.tooltip:before {
  content: "";
  position: absolute;
  inset: var(--t) 0;
  border-image: fill 0 / 0 var(--t) / var(--h) 0
    conic-gradient(#CC333F 0 0); /* the background color */
  clip-path: inherit;
}

Nothing drastic has changed. We introduced a new variable to control the border thickness (--t) and updated the clip-path property with the new variables that define the tail’s dimensions.

Now, all the work will be done on the pseudo-element’s clip-path property. It will no longer inherit the main element’s value, but it does need a new value to get the correct border thickness around the tail. I want to avoid getting deep into the complex math behind all of this, so here is the implementation:

clip-path: 
  polygon(0 100%, 0 0, 100% 0, 100% 100%,
    min(100% - var(--t), var(--p) + var(--h)tan(var(--a)/2) - var(--t)tan(45deg - var(--a) / 4)) 100%,
    var(--p) calc(100% + var(--h) + var(--t)(1 - 1/sin(var(--a)/2))),
    max(var(--t), var(--p) - var(--h)tan(var(--a)/2) + var(--t)*tan(45deg - var(--a)/4)) 100%);

It looks complex because it is! You don’t really need to understand the formulas since all you have to do is adjust a few variables to control everything.

Now, finally, our tooltip is perfect. Here is an interactive demo where you can adjust the position and the thickness. Don’t forget to also play with the dimension of the tail as well.

Let’s move on to the rounded corners. We can simply use the code we created in the previous article. We duplicate the shape using a pseudo-element and make a few adjustments for perfect alignment and a correct border thickness.

The reason I’m not going into details for this one is to make the point that you don’t have to remember all the various use cases and code snippets by heart. The goal is to understand the actual concepts we are using to build the tooltips, like working with border-image, clip-path(), gradients, and math functions.

I can’t even remember most of the code I write after it’s done, but it’s no issue since all I have to do is copy and paste then adjust a few variables to get the shape I want. That’s the benefit of leveraging modern CSS features — they handle a lot of the work for us.

Border-Only Tooltips

I’d like to do one more exercise with you, this time making a tooltip with no fill but still with a full border around the entire shape. So far, we’ve been able to reuse a lot of the code we put together in Part 1, but we’re going to need new tricks to pull this one off.

The goal is to establish a transparent background while maintaining the border. We’ll start without rounded corners for the moment.

See how we’re going to be working with gradients again? I could have used a single color to produce a solid, single-color border, but I put a hard stop in there to demonstrate the idea. We’ll be able to create even more variations, thanks to this little detail, like using multiple colors, different color stops, and even different types of gradients.

You’ll see that the code looks fairly straightforward:

.tooltip {
  /* tail dimension */
  --a: 90deg; /* angle */
  --h: 1em; /* height */

  --p: 50%; /* tail position */
  --b: 7px; /* border thickness */

  position: relative;
}
.tooltip:before {
  content: "";
  position: absolute;
  inset: 0 0 calc(-1*var(--h));
  clip-path: polygon( ... ); /* etc. */
  background: linear-gradient(45deg, #cc333f 50%, #79bd9a 0); /* colors */
}

We’re using pseudo element again, this time with a clip-path to establish the shape. From there, we set a linear-gradient() on the background.

I said the code “looks” very straightforward. Structurally, yes. But I purposely put a placeholder clip-path value because that’s the complicated part. We needed to use a 16-point polygon and math formulas, which honestly gave me big headaches.

That’s why I turn to my online generator in most cases. After all, what’s the point of everyone spending hours trying to suss out which formulas to use if math isn’t your thing? May as well use the tools that are available to you! But note how much better it feels to use those tools when you understand the concepts that are working under the hood.

OK, let’s tackle rounded corners:

For this one, we are going to rely on not one, but two pseudo-elements, :before and :after. One will create the rounded shape, and the other will serve as the tail.

The above figure illustrates the process for creating the rounded part with the :before pseudo-element. We first start with a simple rectangular shape that’s filled with a conic gradient containing three colors. Then, we mask the shape so that the inner area is transparent. After that, we use a clip-path to cut out a small part of the bottom edge to reserve space for the tail we’ll make with the :after pseudo-element.

/* the main element */
.tooltip {
  /* tail dimension */
  --a: 90deg; /* angle */
  --h: 1em; /* height */

  --p: 50%; /* tail position  */
  --b: 7px; /* border thickness */
  --r: 1.2em; /* the radius */

  position: relative;
  z-index: 0;
}

/* both pseudo-elements */
.tooltip:before,
.tooltip:after {
  content: "";
  background: conic-gradient(#4ECDC4 33%, #FA2A00 0 66%, #cf9d38 0);  /* the coloration */
  inset: 0;
  position: absolute;
  z-index: -1;
}

/* the rounded rectangle */
.tooltip:before {
  background-size: 100% calc(100% + var(--h));
  clip-path: polygon( ... );
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  padding: var(--b);
}

/* the tail */
.tooltip:after {
  content: "";
  position: absolute;
  bottom: calc(-1 * var(--h));
  clip-path: polygon( ... );
}

Once again, the structure is not all that complex and the clip-path value is the tough part. As I said earlier, there’s really no need to get deep into an explanation on it when we can use the points from an online generator to get the exact shape we want.

The new piece that is introduced in this code is the mask property. It uses the same technique we covered in yet another Smashing article I wrote. Please read that for the full context of how mask and mask-composite work together to trim the transparent area. That’s the first part of your homework after finishing this article.

Fun Tail Shapes

We’ve covered pretty much every single one of the tooltips available in my collection. The only ones we have not specifically touched use a variety of different shapes for the tooltip’s tail.

All of the tooltips we created in this series used a simple triangle-shaped tail, which is a standard tooltip pattern. Sure, we learned how to change its dimensions and position, but what if we want a different sort of tooltip? Maybe we want something fancier or something that looks more like a speech or thought bubble.

If the rounded corners in the last section are the first part of your homework, then the next part is to try making these tail variations yourself using what we have learned together in these two articles. You can always find the code over at my collection for reference and hints. And, leave a comment here if you have any additional questions — I’m happy to help!

Conclusion

I hope you enjoyed this little series because I sure had a blast writing it. I mean, look at all of the things we accomplished in a relatively short amount of space: simple rectangular tooltips, rounded corners, different tail positions, solid and gradient backgrounds, a bunch of border options, and finally, custom shapes for the tail.

I probably went too far with how many types of tooltips we could make — there are 100 in total when you count them up! But it goes to show just how many possibilities there are, even when we’re always using the same single element in the HTML.

And, it’s great practice to consider all of the different use cases and situations you may run into when you need a tooltip component. Keep these in your back pocket for when you need them, and use my collection as a reference, for inspiration, or as a starting point for your own work!

Further Reading On SmashingMag

How To Engage More Developers With Open Source Projects

Fix: Developer Chasm To Engage More Devs With My Open Source Project

Wish I could push that git commit to move beyond initial developer engagement. A developer chasm means getting stuck with open-source community growth after initial engagement.

In this article, I will share the insights that helped me successfully move open-source projects from the initial developer engagement stage to the category leader stage with community-led growth. I learned from my developer community-building work and developer relations consultant work for open-source projects.