Codit Wiki

Loading information... Please wait.

Codit Blog

Posted on Thursday, June 1, 2017 3:30 PM

Stijn Moreels by Stijn Moreels

One of the mind-blowing development techniques that radically changed the programming world is the Test-Driven Development approach introduced by Kent Beck.

But... writing tests before we start coding? Who will do that?


One of the mind-blowing development techniques that radically changed the programming world; is the Test-Driven Development.

Writing tests before we start coding? Who will do that?

I must admit that I personally wasn’t really convinced by the idea; maybe because I didn’t quite understand the reason we should write our tests first and the way we should do it. Can you have a bad Software Design with TDD? Can you break your Architecture with TDD? Yes! TDD is a discipline that you should be following. And like any discipline you must hold to a certain number of requirements. By the end of the day, it’s YOUR task to follow this simple mindset.

In this article, I will talk about the Mindset introduced by Kent Beck when writing in a Test-Driven Development environment.

Too many developers don’t see the added-value about this technique and/or don’t believe it works.

TDD works!

"Testing is not the point; the point is about Responsibility"
-Kent Beck


Because so many of us don’t see the benefits of TDD, I thought it would make sense to specify them for you. Robert C. Martin has inspired me with this list of benefits.

Increased Certainty

One of the benefits is that you’re certain that it works. Users have more responsibility in a Test-Driven team; because they will write the Acceptance Tests (with help of course), and they will define what the system must do. By doing so, you’re certain that what you write is what the customer wants.

The amount of uncertainty that builds up by writing code that isn’t exactly what the customer wants is called: The Uncertainty Principle. We must always eliminate this uncertainty.

By writing tests first; you can tell your manager and customer: “Yes, it will work; yes, it’s what you want”.

Defect Reduction

Before I write in a Test-First mindset; I always thought that my code was full of bugs and doesn’t handle unexpected behavior.
Maybe it was because I’m very certain of myself; but also, because I wrote the tests after the code and was testing what a just wrote; not what I want to test.

This increases the Fake Coverage of your code.

Increased Courage

So many developers are “afraid” to change something in their code base. They are afraid to break something. Why are they afraid? Because they don’t have tests!

“When programmers lose the fear of cleaning; they clean”
- Robert C. Martin

A professional developer doesn’t allow that his/her code rots; so, you must refactor with courage.

In-Sync Documentation

Tests are the lowest form of documentation of your code base; always 100% in sync with the current implementation in the production code.

Simple Design

TDD is an analysis/design technique and not necessary a development technique. Tests force you to think about good design. Certainly, if you write them BEFORE you write the actual implementation. If you do so, you’re writing them in offence and not in defense (when you’re writing them afterwards).

Test-First also helps you think about the Simplest thing that could possibly work which automatically helps you to write simple structured designed code.

Test-First Mindset

When you’re introduced into the Test-First methodology, people often get Test Infected. The amount of stress that’s taking from you is remarkable. You refactor more aggressively your code without any fear that you might break something.

Test-Driven Development is based on this very simple idea to first write your test, and only then write your production code. People underestimate the part “first write your test”. When you writing your tests, you’re solving more problems than you think.

Where should I place this code? Who’s responsible for this logic? What names should I use for my methods, classes…? What result must a get from this? What isn’t valid data? How will my class interface look like? …

After trying to use TDD in my daily practice, if found myself always asking the same questio:

“I would like to have a … with … and …”

Such a simple idea changed my vision so radically about development and I’m convinced that by using this technique, you’re writing simpler code because you always think about:

“What’s the simplest thing that could make this test work”

If you find that you can implement something that isn’t the right implementation, write another test to expose this behavior you want to implement.

TDD is - in a way - a physiological methodology. What they say is true: you DO get addicted to that nice green bar that indicate that you’re tests all pass. You want that color as green as possible, you want it always green, you want it run as fast as possible so you can quickly see it’s green…

To be a Green-Bar-Addict is a nice thing.

Kent Beck Test-Patterns

It felt a little weird to just state all the patterns Kent Beck introduced. Maybe you should just read the book Test-Driven Development by Example; he’s a very nice writer and I learned a lot from the examples, patterns and ideas.

What I will do, is give you some basic patterns I will use later in the example and some patterns that we very eye-opening for me the first time.

Fake It

When Kent talked about “What’s the simplest thing that could work”, I was thinking about my implementation but what he meant was “What’s the simplest thing that could work for this test”.

If you’re testing that 2 x 3 is 6 than when you implement it, you should Fake It and just return the 6.

Very weird at first, especially because the whole Fake It approach is based on duplication; the root of all software evil. Maybe that’s the reason experienced software engineers are having problems with this approach.

But it’s a very powerful approach. Using this technique, you can quickly get the bar green (testing bar). And the quicker you get that bar green, the better. And if that means you must fake something; then you should do that.


This technique I found very interesting. This approach really drives the abstraction of your design. When you find yourself not knowing what to do next, or how you should go further with your refactoring; write another test to support new knowledge of the system and the start of new refactorings in your design.

Especially when you’re unsure what to do next. 

If you’re testing that 2 x 3 is 6 than in a Triangulation approach you will first return 6 and only change that if you’re testing again but then for 2 x 2 is 4.

Obvious Implementation

Of course: when the implementation is so simple, so obvious, … Than you could always implement it directly after your test. But remember that this approach is only the second option after Fake It and Triangulation.

When you find yourself taking steps that are too big, you can always take smaller steps.

If you’re testing that 2 x 3 is 6, in an Obvious Implementation approach you will just write 2 x 3 right away.

By Example

I thought it would be useful to show you some example of the TDD workflow. Since everyone is so stoked about test-driving Fibonacci I thought it would be fun to test-drive another integer sequence.

Let’s test-drive the Factorial Sequence!

What happens when we factorial 4 for example? 4! = 4 x 3 x 2 x 1 = 24


But let’s start with something super simple:

Always start with the same sentence: “I would like to have a… “. I would like to have a method called Factorial which I could use to send an integer with that will calculate the factorial integer for me.

Now we have created a test before anything about factorial is implemented.


Now we have the test, let’s start now by making our code compile again.

Let’s test this:

Hooray! We have a failed test == progress!


First Steps

What’s the simplest thing that we could write in order that this test will run?

Hooray! Our test passed, we can go home, right?

A Bit Harder

What’s next? Let’s check. What happens if we would test for another value?

I know, I know. Duplication, duplication, duplication. But were testing now right, not yet in the last step of the TDD mantra.

What is the simplest we could change to make this test pass?

Yes, I’m feeling good right now. A nice green bar.

One Step Before Generalize

Let’s add just another test, a bit harder this time. But these duplication is starting to irritate me; you know the mantra: One-Two-Three-Refactor? This is the third time, so let’s start refactoring!

Ok, what’s the simplest thing?


Ok, we could add if/else-statements all day long, but I think it’s time to some generalization. Look at what we’ve now been implementing. We write 24 but do we mean 24?

Remembering Factorial, we mean something else:

All still works, yeah. Now, we don’t actually mean 4 by 4 do we. We actually mean the original number:

And we don’t actually mean 3, 2, and 1 by 3, 2 and 1, we actually mean the original number each time mins one. So, actually the Factorial of the 3! could you say, no?

Let’s try:

Wow, still works.Wait, isn’t that if-statement redundant? 2 x 2! == 2 right?


Now, the factorial of 0, is also 1. We haven’t tested that haven’t we? We have found a boundary condition!

This will result in a endless loop because we will try to factorial an negative number; and since factorial only happens with positieve numbers (because the formula with negative integers will result in a division by zero and so, blocking us for calculating a factorial value for these negative integers).

Again, simplest thing that could work?

Now, the last step of TDD is always Remove Duplication which in this case is the 1 that’s used two times. Let’s take care of that:

Hmm, someone may have noticed something. We could actually remove the other if-statement with checking for 1 if we adapt the check of 0. This will return 1 for us in the recursive call:

By doing this, we also have ruled out all the other negative numbers passed inside the method.


Why oh why are people so skeptic about Test-Driven Development. If you look at the way you use it in your daily practice, you find yourself writing simpler and more robust code.

TDD is actually a Design Methodology and not a Development Methodology. The way you think about the design, the names, the structure… all that is part of the design process of your project. The tests that you have is the added value of this approach and makes sure that you can refactor safely and are always certain of your software.

Start trying today in your daily practice so you stop thinking about: How will you implement it? but rather:

How will you test it?


Categories: Technology
written by: Stijn Moreels

Posted on Thursday, June 1, 2017 8:00 AM

Luis Delgado by Luis Delgado

During //Build, Microsoft surprised the market with the CosmosDb announcement. With the announcement, Microsoft made some very bold statements about the service, particularly about scalability and performance. I was particularly curious about the sub-10-millisecond write performance promised at the 99th percentile, which also included the indexing overhead on writes.

At Codit, we are regularly engaged in customer IoT projects. By nature, IoT projects generate vasts amounts of data that need to be quickly ingested and stored. So with this in mind, I wanted to test how CosmosDb behaves when it needs to ingests large batches of historical observations.

The data set

To run the experiment, I used the historical flight data available here. The data model includes about 110 columns, out of which I picked the first 50 columns. I got about 5Gb of data comprised of millions of these rows. Each row is about 1725 bytes in size.

The CosmosDb setup

Since the experiment data is tabular in nature, I created a Table API database with one collection called flights.

Next, I wrote a C# program that would read the csv files from the dataset (each one is about 200Mb) and created a TableEntity using the DynamicTableEntity approach. I then grouped all rows based on their airport’s IATA code, which I decided to use as the PartitionKey for this experiment. Finally, the program creates insert batches of length 100 for every group of rows belonging to the same airport code. The program then takes each of these insertion batches (remember, each batch has up to 100 rows to insert) and executes them sequentially.

To reduce network latency, I provisioned an Azure VM in the same region as the CosmosDb (North Europe) and gave it a generous amount of RAM (12Gb) so it could load all the data set in memory (the program I wrote is not optimized to reduce memory consumption).

The result

  1. Overall, the program created 19005 insert batches, most of them holding 100 rows to insert.
  2. The program managed to execute 4–5 batches per second. This means it managed to insert about 400–500 rows/s. This is about 860KB/s throughput.
  3. The 96th percentile for batch insertion time (remember, we are talking about insertion of a batch that includes 100 rows, not about inserting individual rows) was 283ms.


With this experiment, I managed to hit 429 errors very quickly. At the end, I needed to increase the RU/s to 10'000. But most importantly, I needed to change the indexing policy from consistent to lazy. With the amount of data I was trying to load, I was not able to avoid 429 errors (RequestTooLarge) with a consistent indexing policy, not even when using 10'000 RU/s.

Write performance is excellent, as you can see from the result above. Even when using consistent indexing policy, the write performance of the batches was very high (when you don’t get throttled).

As typical for a v1 product, there are some inconsistencies between the service documentation and the actual APIs. For example, the documentation states that CosmosDb is not limited to the 100 rows/insert batch as Azure Table storage is. However, when building insertion batches with more than 100 entities, the program throws an exception: The maximum number of operations allowed in one batch has been exceeded, even though I am using the new WindowsAzure.Storage-PremiumTable library. I guess this new library is not updated. I did not try to insert batches using the REST API directly (the documentation only talks about working with .NET, there is no REST reference for the TableDB API).

I think the key takeaway for me is that, when designing a large-scale system with CosmosDb, you will have to be extremely diligent on calculating how much capacity the system will need to offer, and its corresponding cost trade-off. Getting large write throughput on this database seems to be expensive. On the other hands, I ran the same loading job against the traditional Azure Table Storage service, and I never got throttled at all. In summary, I can derive the following learnings:

  1. The performance of individual writes of CosmosDb is excellent.
  2. Getting high write throughput with consistent indexing is significantly more expensive on CosmosDb than Table Storage. Table Storage will give you way more throughput for less money.
  3. You should carefully optimize your CosmosDb index. Although the database advertises that everything is indexed by default (which is a great engineering feat, no question about it), the overhead of indexing everything is going to cost you money, especially if your data model is large.
  4. CosmosDb Table API effectively supports secondary indexes, whereas Table Storage only supports PartitionKey-RowKey indexing. This is a big advantage for CosmosDb when you need to run more complex queries.


Here is the code I used to load the CSV files into CosmosDb. The code is light based on the Microsoft sample.

Here is the link to one of those CSV files.


With some time in my hands, I refactored the code to execute the insert batches in parallel and do a more detailed write throughput comparison with the standard Azure Table Storage Table. In the refactoring I also decided to pick only 20 columns of the data set, and deserialize them a proper class to get the correct data types (instead of having them all as string). The conclusions don’t change, but I can offer now additional hard facts.

In the following screenshots, you’ll see rows with three values: the first value is the timestamp of the row insertion batch (remember, each batch contains up to 100 rows), the second value is the ellapsed time for inserting the batches in milliseconds, and the last value is the total amount of rows inserted.

Azure Table storage, 10 parallel batches of 100 rows per batch


CosmosDb, 10 parallel insert batches of 100 rows per batch, consistent indexing, 10KRU/s. Basically useless, no request succeeds

CosmosDb, 10 parallel batches of 100 rows per batch, lazy indexing, 5K RU/s

You can see that the write performance of CosmosDb is much better than that of Azure Table storage (just compare the batches with 1000 records, many of them hover around 100ms). That is, when you don’t get throttled.

Categories: Azure
Tags: CosmosDb, Storage
written by: Luis Delgado

Posted on Wednesday, May 31, 2017 3:48 PM

Sam Vanhoutte by Sam Vanhoutte

What can we learn from the WannaCry ransomware attack and the way we tackle Internet of Things (IoT) projects? That we had better invest enough resources to make, and keep, our smart devices safe.

I was at the airport of Seattle, returning from the Microsoft Build Conference, when I saw the outbreak of the WannaCry ransomware trending on Twitter. There was talk of hospitals that couldn’t operate anymore, government departments unable to function, public transport issues... All consequences of the virus that spread from computer to computer, looking for new victims. The consequences for many IoT scenarios around the world played through my mind. I also remembered the conversations I've had with partners and clients over the past years about investing time and money in the security and safe keeping of IoT devices.

The WannaCry story clearly demonstrated that there was a crushing responsibility for various IT service companies. They should have kept computer systems up to date with a supported Windows version and the latest security updates. Very often, time, budget or change management is a reason why such updates did not happen. "It it’s not broken, don’t fix it." Such thinking left the back door to several critical systems wide open, which made things broken a lot quicker than anyone assumed.

That's why, starting with Windows 10, Microsoft has changed the default 'update policy'. Security and system updates are automatically installed, giving customers a Windows system that is up to date by default. However, the pushing of automatic updates is a major problem with most IoT systems available today.

IoT security with holes

Very often, devices - from smart scales and to internet thermostats to even healthcare devices – are not equipped to receive security updates. The software often does not allow it, or the computing power of the device is too limited to deal with the update logic.

In most cases, the users of such a device don’t think about by the fact that their gadget (or more dangerously, their health device) is actually a mini computer that may have a security issue. If security updates cannot be pushed by default through the manufacturer’s IoT platform, you can assume that the device will never be updated during its entire lifecycle. To make matters worse, such devices often have a long lifespan. Thus, the encryption algorithms used today will no longer prove sufficient to keep sensitive data encrypted in the foreseeable future.

Companies should therefore always supply an update mechanism in their IoT solution. This makes the initial investment higher, but it also offers an undeniable advantage. For one thing, pushing updates can prevent your brand from getting negative exposure in the news as the result of a (serious) vulnerability. But you can also send new pieces of functionality to those devices. This keeps the devices relevant and enables you to offer new features to your customers.

By taking the responsibility for updating (and thus securing) such systems away from the end user, we create a much safer internet. Because no one wants his smart toaster (and its internet connection) used to enable drug trafficking, child pornography or terrorism.


Note: This article was first published via Computable on 30 May 2017 (in Dutch) 

Categories: Opinions
Tags: IoT
written by: Sam Vanhoutte

Posted on Wednesday, May 24, 2017 12:00 PM

Toon Vanhoutte by Toon Vanhoutte

This blog post covers several ways to optimize the monitoring experience of your Logic Apps. Logic Apps provide two ways to add functional data to your workflow runs: tracked properties and outputs. This functional data can be used to improve operational experience, to find a specific run based on business data and to serve as a base for reporting. Both options are discussed in depth and compared.


Tracked Properties

As the documentation states: Tracked properties can be added onto actions in the workflow definition to track inputs or outputs in diagnostics data. This can be useful if you wish to track data like an "order ID" in your telemetry

Tracked properties can be added in code view to your Logic Apps actions in this way:


As the documentation states: Outputs specify information that can be returned from a workflow run. For example, if you have a specific status or value that you want to track for each run, you can include that data in the run outputs. The data appears in the Management REST API for that run, and in the management UI for that run in the Azure portal. You can also flow these outputs to other external systems like PowerBI for creating dashboards. Outputs are not used to respond to incoming requests on the Service REST API

Outputs can be added in code view to your Logic Apps workflow in this way. Remark that you can also specify their data type:

Runtime Behaviour

Do runtime exceptions influence tracking?

What happens if my Logic App fails? Are the business properties still tracked or are they only available in a happy scenario? After some testing, I can conclude the following:

  • Tracked properties are only tracked if the appropriate action is executed.
  • Outputs are only tracked if the whole Logic App completes successfully.

When using tracked properties, my advice is to assign them to the first action (not supported on triggers) of your Logic App, so they are certainly tracked.

Do tracking exceptions influence runtime?

Another important aspect on tracking / monitoring is the fact that it should never influence the runtime behaviour. It's unacceptable that a Logic App run fails, because a specific data field to be tracked is missing. Let's have a look what happens in case we try to track a property that does not exist, e.g.: "Reference": "@{triggerBody()['xxx']}"

In both cases the Logic App ends in a failed state, however there are some differences:

Tracked Properties

  • The action that is configured with tracked properties fails.
  • There is a TrackedPropertiesEvaluationFailed exception.


  • All actions completed successfully, despite the fact that the Logic App run failed.
  • In the Run Details, an exception is shown for the specific output. Depending on the scenario, I've encountered two exceptions:

    >  The template language expression 'triggerBody()['xxx']' cannot be evaluated because property 'xxx' doesn't exist, available properties are 'OrderId, Customer, Product, Quantity'.

    > The provided value for the workflow parameter 'Reference' at line '1' and column '57' is not valid.

Below you can find a screen capture of the workflow details.

This is not the desired behaviour. Luckily, we can easily avoid this. Follow this advice and you'll be fine:

  • For strings: Use the question mark operator to reference potential null properties of an object without a runtime error. In case of a null reference, an empty string will be tracked. Example: "Reference": "@{triggerBody()?['xxx']}"

  • For integers: Use the int function to convert the property to an integer, in combination with the coalesce function which returns the first non-null object in the arguments passed. Example: "Quantity": "@int(coalesce(triggerBody()?['xxx'], 0))"

Azure Portal

The first place where issues are investigated is the Azure Portal. So it would be very helpful to have these business properties displayed over there. Tracked properties are nowhere to be found in the Azure Portal, but fortunately the outputs are displayed nicely in the Run Details section. There is however no option to search for a specific Logic App run, based on these outputs.

Operations Management Suite

In this post, I won't cover the Logic Apps integration with Operations Management Suite (OMS) in depth, as there are already good resources available on the web. If you are new to this topic, be sure to check out this blog post and this webcast.

Important take-aways on Logic Apps integration with OMS:

  • Only tracked properties are available in OMS, there's no trace of outputs within OMS.
  • OMS can be used to easily search a specific run, based on business properties
    > The status field is the status of the particular action, not of the complete run
    > The resource runId can be used to find back the run details in the Azure Portal

  • OMS can be used to easily create reports on the tracked business properties
  • Think about data retention. The free pricing tier gives you data retention of 7 days.

Management API

Another way to search for particular Logic Apps runs, is by using the Azure Service Management API. This might come in handy if you want to develop your own dashboard on top of Logic Apps.
The documentation clearly describes operations available to retrieve historical Logic Apps run in a programmatic way. This can be done easily with the Microsoft.Azure.Management.Logic library. Outputs are easier to access than tracked properties, as they reside on the WorkflowRun level. The following code snippet can serve as a starting point:

Unfortunately, the filter operations that are supported are limited to the ones available in the Azure Portal:

This means you can only find specific Logic Apps runs - based on outputs or tracked properties - if you navigate through all of them, which is not feasible from a performance perspective.



Below you can find a comparison table of the investigated features. My current advice is to use both of them, as you'll get the most in return. 

Feature Tracked Properties Outputs
Tracking Level Action Logic App Run
Runtime behaviour    If action executes If Logic App succeeds 
Azure Portal No integration Visible in run details
OMS Full integration No integration
Management API No search No search

Feedback to Product Team

Monitoring is one of areas that needs some improvements to provide all we need for operating and monitoring an integration environment. Here are my feature requests in order of priority:

  • Ensure outputs are also monitored in case a workflow run fails. Vote here.
  • Provide OMS integration for outputs. Vote here.
  • Extend the search filter in the Management API. Vote here.
  • Provide a unique URL to directly redirect to a specific Logic App run.

Hope this post clarifies the monitoring capabilities of Logic Apps. 

Feel free to vote for the mentioned feature requests!

Categories: Azure
Tags: Logic Apps
written by: Toon Vanhoutte

Posted on Friday, May 19, 2017 11:29 AM

Toon Vanhoutte by Toon Vanhoutte

Receiving data from a SQL table and processing it towards other back-end systems; It's a very common use case in integration. Logic Apps has all the required functionality in its toolbox to fulfill this integration need. This blog post explains how you can do this in a reliable fashion, in case you're dealing with mission critical interfaces where no data loss is accepted.


Let's discuss the scenario briefly.  We need to consume data from the following table.  All orders with the status New must be processed!

The table can be created with the following SQL statement:

First Attempt


To receive the data, I prefer to create a stored procedure. This avoids maintaining potentially complex SQL queries within your Logic App. The following stored procedure selects the first order with status New and updates its status to Processed in the same statement. Remark that it also returns the @@ROWCOUNT, as this will come in handy in the next steps.

The Logic App fires with a Recurrence trigger.  The stored procedure gets executed and via the ReturnCode we can easily determine whether it returned an order or not.  In case an order is retrieved, its further processing can be performed, which will not be covered in this post.


If you have a BizTalk background, this is a similar approach on using a polling SQL receive location. One very important difference: the BizTalk receive adapter executes the stored procedure within the same distributed transaction as it persists the data in the MessageBox, whereas Logic Apps is completely built on API's that have no notion of MSDTC at all.

In failure situations, when a database shuts down or the network connection drops, it could be that the order is already marked as Processed, but it never reaches the Logic App. Depending on the returned error code, your Logic App will end up in a Failed state without clear description or the Logic App will retry automatically (for error codes 429 and 5xx). In both situations you're facing data loss, which is not acceptable for our scenario.

Second attempt


We need to come up with a reliable way of receiving the data. Therefore, I suggest to implement a similar pattern as the Azure Service Bus Peek-Lock. Data is received in 2 phases:

  1. You mark the data as Peeked, which means it has been assigned to a receiving process
  2. You mark the data as Completed, which means it has been received by the receiving process

Next to these two explicit processing steps, there must be a background task which reprocesses messages that have the Peeked status for a too long duration. This makes our solution more resilient.

Let's create the first stored procedure that marks the order as Peeked.

The second stored procedure accepts the OrderId and marks the order as Completed.

The third stored procedure should be executed by a background process, as it sets the status back to New for all orders that have the Peeked status for more than 1 hour.

Let's consume now the two stored procedures from within our Logic App.  First we Peek for a new order and when we received it, the order gets Completed.  The OrderId is retrieved via this expression: @body('Execute_PeekNewOrder_stored_procedure')?['ResultSets']['Table1'][0]['Id']

The background task could be executed by a SQL Agent Job (SQL Server only) or by another Logic App that is fired every hour.


Happy with the result? Not a 100%! What if something goes wrong during further downstream processing of the order? The only way to reprocess the message is by changing its status in the origin database, which can be a quite cumbersome experience for operators. Why can't we just resume the Logic App in case of an issue?

Third Attempt


As explained over here, Logic Apps has an extremely powerful mechanism of resubmitting workflows. Because Logic Apps has - at the time of writing - no triggers for SQL Server, a resubmit of the Recurrence trigger is quite useless. Therefore I only want to complete my order when I'm sure that I'll be able to resubmit it if something fails during its further processing. This can be achieved by splitting the Logic App in two separate workflows.

The first Logic App peeks for the order and parses the result into a JSON representation. This JSON is passed to the next Logic App.

The second Logic App gets invoked by the first one.  This Logic App completes the order first and performs afterwards the further processing.  In case something goes wrong, a resubmit of the second Logic App can be initiated.


Very happy with the result as:

  • The data is received from the SQL table in a reliable fashion
  • The data can be resumed in case further processing fails


Don't forget that every action is HTTP based, which can have an impact on reliability. Consider a two-phased approach for receiving data, in case you cannot afford message loss. The same principle can also by applied on receiving files: read the file content in one action and delete the file in another action. Always think upfront about resume / resubmit scenarios. Triggers are better suited for resubmit than actions, so if there are triggers available: always use them!

This may sound overkill to you, as these considerations will require some additional effort. My advice is to determine first if your business scenario must cover such edge case failure situations. If yes, this post can be a starting point for you final solution design.

Liked this post? Feel free to share with others!



Categories: Azure
written by: Toon Vanhoutte