Receiving, Decoding & Processing LoRaWAN Uplinks in AWS

Chloe McAree

In the previous blog in this series, we got our LoRaWAN gateway connected to AWS IoT Core for LoRaWAN and successfully streaming uplinks. That’s a big milestone as the devices are now able to send messages securely into AWS.

LoRaWAN devices are intentionally lightweight and send encoded payloads (usually binary) to save power and bandwidth. Our work now shifts from connectivity to interpretation as the real value comes from receiving, decoding, and processing these uplinks. In AWS, we’ll use IoT Rules and Lambda functions to transform these uplinks into useful, structured data.

This blog will explore the architecture patterns, the lifecycle of an uplink, and the design choices you face when building a scalable ingestion pipeline on AWS.

AWS IoT Core’s Role in Uplink Processing

When a LoRaWAN device transmits an uplink, AWS does a few things automatically:

  • Validates and normalises the LoRaWAN metadata
  • Publishes the message to a predictable topic structure
  • Enriches the event with gateway, RSSI, SNR, FPort, etc.

All LoRaWAN uplinks arrive under this topic:

`device/uplink/<DevEui>`

An IoT topic is a named channel that your devices send (publish) and receive (subscribe to) messages in AWS IoT Core. This is your “entry point” into AWS.

But IoT Core is intentionally neutral. It doesn’t decode payloads, store data, or run workflows. Instead, it relies on IoT Rules to decide what should happen next.

The Role of IoT Rules

IoT Rules are like message routers and operate in an if-this-then-that (IFTTT) style. Overall, they allow you to process your incoming device data and route the data downstream to other AWS services, so you can do something like this:

“When an uplink arrives on topic X, send it to service Y.”

IoT Core rules can filter messages, transform data and can publish data to one or more services.

Rule Statements

The rules evaluate messages using a SQL-like query.

For example, if you had an end device that records temperature, you might use one of the following SQL-like filters in your rule:

If you wanted to just take all data from the uplink and log it in CloudWatch you could use this:

”’
SELECT *

FROM ‘insert-your-iot-topic’

”’

Or you could choose to do a level of processing here, for example if you only want to action data if the temperature is above a certain range you could do:

”’

SELECT temperature, humidity

FROM ‘insert-your-iot-topic’

WHERE temperature > 30

”’

Here is a screenshot of what these rules look like in the console. We create them via CDK so that we can maintain them easier. In the screenshot you will see that you can also use wildcards in the topic names so here we have used `device/uplink/#` we don’t specify a specific devEui, we tell it to route through this rule for an uplink from any device.

Rule Actions

Rule actions are what happens when your SQL condition matches and they allow you to trigger one or more AWS services and send that data to them for further processing or analysis.

Common service targets include:

  • CloudWatch Logs – for debugging early in the project
  • Lambda – for lightweight decoding or enrichment
  • SQS – for building resilient ingestion pipelines
  • SNS – for notifications and triggering alerts
  • DynamoDB – for storing data
  • S3 – for archiving data
  • Kinesis / Firehose – for streaming and analytics

Here is an example of the drop-down selection when choosing an action target:

When triggering any service from your action, you also need to ensure you have an IAM Role set up that grants permission to the target service. E.g. permission to invoke a Lambda Function.

Error Actions

When working with rules, you can set up actions for when your condition matches, but you can also optionally set up error actions, that get triggered if your main action fails. This could allow you to send the failed messages to CloudWatch for debugging or you could republish it to an error topic for separate processing etc.

Direct-to-Lambda vs. SQS Pipelines

Many tutorials show the direct pattern:

IoT Rule → Lambda → Database

It’s fast, easy, and ideal for prototypes. But production systems almost always evolve into:

IoT Rule → SQS Queue → Consumer Lambda(s)

SQS typically gets added for the following reasons:

  1. Decoupling – Your devices keep running even if downstream processing breaks
  2. Automatic Retries – SQS retries failures without involving the device
  3. Dead Letter Queues – Bad messages don’t get lost; they get quarantined for inspection
  4. Scaling and Batching – Consumer Lambdas can scale independently and process messages in batches, reducing cost
  5. Fan out – One uplink can feed multiple pipelines (analytics, alerts, storage, ML).

Even if you start direct-to-Lambda, you’ll likely migrate to an SQS-based approach later.

What Makes Payload Decoding Hard?

Decoding is often underestimated. Some challenges include:

  • Different vendors use different binary formats
  • FPort values may correspond to different message types
  • Sensors may pack values using bit-shifts or sign bits
  • Firmware updates sometimes change formats
  • Payload size restrictions encourage unusual compression tricks

IoT engineers end up maintaining decoder libraries, often per firmware version. This is why your pipeline should be easy to modify and redeploy. Payload formats change.

What Should Your Output Look Like?

Once decoded, you want a predictable structure. A good, decoded uplink includes:

  • dev_eui
  • timestamp
  • fport
  • payload_raw_hex
  • Device-specific fields (temperature, tilt, GPS, etc.)
  • Decoder version (important for debugging)
  • Signal metadata (RSSI, SNR, gateway IDs)

Consistency is critical, as downstream systems depend on it.

IoT Architecture Is About Flexibility

When designing IoT uplink pipelines, the most important insight is this:

You don’t know how your system will evolve yet. Build for change.

  • Device payloads evolve
  • New sensor types join the fleet
  • You add analytics, ML, health monitoring, dashboards, alert systems
  • You start caring about cost or performance or compliance

Your initial pipeline is rarely your final pipeline.

This is why AWS gives you modular building blocks (Rules, SQS, Lambda) rather than a rigid end-to-end flow.

Summary

Here is a summary of what your architecture might look like end to end:

  1. Device sends compressed binary payload
  2. Gateway forwards to AWS IoT Core
  3. AWS publishes normalized event to an IoT topic
  4. IoT Rule routes the message to CloudWatch for debugging but also adds the message to SQS that has a Lambda consumer.
  5. The Lambda consumes the messages from SQS in batches and decodes their payload into human-readable JSON format.
  6. The Lambda at this point could publish this decoded message to another IoT topic which has SQS as an action and a different Lambda consumer.
  7. This Lambda consumer, could batch read the decoded data and write them to your database of choice e.g. AWS Timestream.

Your IoT implementation may follow different technologies, and your devices will have different payloads, but overall, the goal remains the same, your uplinks are raw data, and you need to transform them into meaningful information.

Read the next blog in this series here. 

Read the previous blog in this series here.

LETS TALK.

Want to find out how the subject of this blog could help your business? 

Our blended team of experts go over and above with our services to our customers, no matter what the challenge. Get in touch to find out how we can work together.