Skip to content


How IoT Works: Thing-End

There’s more that goes into IoT development than initially meets the eye. Between the sheer number of available options and the break-neck pace of innovation that we’ve seen over the past few years, nailing down just what goes into a successful IoT project is a challenge. That doesn’t stop us from believing it’s very possible.

Any technology- whether it’s your home computer, your car, or your smart air monitor- has a tech stack that spans from electrons circling around the hardware at the bottom to highly abstracted code running on top. Simply put, the stack defines the parts and their arrangement or architecture.

IoT technology, however, defies the traditional front-end/back-end stack distinctions that we find in fields like web development. Instead of a web page in the front and a server in the back, IoT relies on an entire ecosystem.

That’s why we’re breaking the IoT tech stack down into the following categories:

  • Thing-end
  • User-end
  • Cloud-end

This article is the first in our series on how IoT works. Stay tuned for our coming articles on the other IoT stacks and a final wrap-up on how we connect them all together.


When we’re talking about the thing-end in an IoT system, everything starts with hardware engineering because these parts influence everything else that goes into our device. Just like a house’s foundation serves as a basis for the rest of the structure, hardware forms the foundation for our tech stack. 


First, we have controllers, which create the compute backbone of our solution by performing arithmetical and logical operations.

We commonly use microcontrollers, or MCUs, because they contain everything we need to start computing: CPU for processing, RAM for short-term data storage, ROM for long-term storage, and peripherals like USB ports or GPIO pins.

These range from tiny 8-bit system-on-a-chip (SOC) controllers for the most lightweight applications to more full-featured single board computers (SCBs) like the popular Raspberry Pi.


Second, we need to put the internet into our thing, so it’s time for connectivity. We need to choose the right option for our connected devices because each brings trade-offs between power consumption, bandwidth, and range. Until Starlink brings global connectivity to IoT, we’ll always have to make cuts somewhere to optimize elsewhere.

For example, an industrial IoT pressure sensor on the factory floor should connect through Ethernet or Wi-Fi because we need reliable, low-latency throughput at a short range, and it shouldn’t be too hard to keep it powered on. An automated sprinkler system in the middle of a field, on the other hand, will want cellular or satellite connectivity because it needs high range, while bandwidth isn’t as big of a concern.


Once we have our Wi-Fi chip, SIM card, or other option installed, it’s time to start interacting with the physical world-after all, that’s the whole point of IoT! We’ll equip our device with sensors and/or actuators, two types of transducers that convert physical phenomena to electrical signals and vice versa. IoT sensors are input, while actuators serve as output.

So, going back to our recent example, the pressure sensor gives us input by taking a measurement and processing the data. From there, it could flip a switch or adjust a dial to raise or lower the pressure as necessary; these are actuators. Or, in the sprinkler system, we’ll use a moisture sensor and an actuator that turns on the water.

Another hardware component in our device-end stack is a security chip called a Hardware Security Module (HSM). As we’ll see in the cloud-end stack, this security chip is crucial for establishing a safe connection for data flow. Very always builds security in from the beginning, and that starts with hardware.

For certain applications, we’ll also use a GPU for edge computing. Some applications require high-resolution graphics rendering, but more often we’ll employ hardware like the NVIDIA Jetson for machine learning (ML) workloads. Instead of sending data to a cloud or gateway device, embedded GPUs allow us to harness AI on the device itself to add a layer of intelligence for autonomous functionality in real-time. Self-driving cars are a common example of embedded GPUs at work.

Very also creates custom parts in order to realize IoT’s limitless potential. 3D printers enable rapid prototyping. We use a Formlabs SLA (stereolithography) printer for intricate details and an FDM (fused deposition modeling) printer when cost and speed are more important. These additive manufacturing methods give us full control over any possibility.

Finally, we tie everything together with circuity. Our engineers use electronic components like resistors, capacitors, and transformers to connect our hardware into a single, seamless device.


Now that we’ve got our physical layer complete, it’s time to start programming. Before we start writing any applications, however, we need firmware, the part of the device-end stack that serves as a bridge between hardware and software. Essentially, firmware is code that directly interfaces with hardware.

While every computer needs firmware, IoT devices pose a unique challenge. Every device is different. Between all the different connectivity options, types of controllers, and even 3D printed parts, we end up with unique hardware architectures that require unique firmware.

That’s why Very uses Nerves. This open-source platform is tailor-made for IoT because it offers unparalleled customizability. Every Nerves device boots into a BEAM Erlang virtual machine, but that’s where the similarities end. Developers can choose what bootloader to use, what parts of the Linux Kernel to utilize, and whether to run applications on bare metal or on top of a fuller operating system.

In truth, firmware actually includes an entire stack of technologies. What’s important to keep in mind, however, is that we package them up under a single roof with Nerves. Some of these technologies include file systems, drivers, and shell environments.

iot software

The top of the thing-end stack is where we tell our thing what to do. Software lets us say something as simple as “read this sensor” or “push this button,” or it can be as complex as defining communication protocols, running algorithms, or querying databases. Just like firmware, software contains a stack of its own, but this time we can break it down into three major categories.

Programming Languages

At the bottom, we have programming languages that “allow us to give instructions in a language the computer understands.” By compiling down to binaries, they let us translate our own ideas into computable logic. Very has a few go-to programming languages that we use for device-end software development. This isn’t a comprehensive list but provides a solid idea of where our focus lies. 

First, we use Elixir. Optimized for IoT, Elixir enables us to create scalable applications that can simultaneously run many processes while also emphasizing simple, resilient code.

Another key device-end language we use is Python. A high-level, abstracted language, Python is today’s most popular language due to its versatility and power. We primarily use it for applications, such as machine learning algorithms, that can’t be built on Elixir.

Finally, we also use C, a massively popular language designed for programming machines, for embedded development.


The second part of the software stack is libraries. Basically, libraries are pre-written code that we can mix, match, and build on top of to create applications. Awesome Elixir libraries include tools for everything from cryptography to geolocation to testing. Python also has a staggering number of libraries, and some of our favorites are in the PyTorch Ecosystem for deep learning.

IoT Application 

The third and final layer of the software stack is the IoT application itself. Yup—we’ve finally arrived at our app! An application is a synthesis of everything that it sits on top of, and in many ways, it’s the reason we started building the device in the first place. Applications collect, process, and communicate data, they control input and output streams, and they are the easiest part of the stack to update or reconfigure.


Although the entire IoT stack needs to work together in harmony for best results, we also see a hierarchical structure emerge where higher layers depend upon the lower ones. Sure, the hardware depends on the software to tell it what to do, but the software needs hardware to even exist in the first place.

Because the stack contains so many interdependencies, we use an agile process to build and iterate upon our design. Of course, everything starts with hardware, but we won’t know which hardware to use if we don’t have a clear picture of the applications that we want to run.

The other takeaway is that the IoT device-end stack offers extreme flexibility. Device development gives us a great opportunity to select the exact technologies we’ll need to accomplish our goals without bringing on any extra baggage. The result is energy efficiency, a smaller attack surface, and dynamic functionality.

It’s how we create the right tool for the job.

So, are you getting excited for your next IoT project? Check out our guide to IoT development frameworks and best practices.

IoT insights delivered to your inbox