Posting SQL Server notifications to Slack


Automation, proactive monitoring, repeatability, reducing waste of time and technical debt. This is something you should know about when trying to do some DevOps.

Why automation? Because you can reduce technical debt and the number of failures that can happen with a manual interaction. You can create environments using a provisioning procedure without falling in common pitfalls like security misconfigurations, wrong configurations and botched monitoring.

Talking about SQL Server, immediate and proactive notifications represent a great step forward toward automation.

We automate whenever we want to stop doing a bunch of recurring or tedious steps manually. At the same time, we are also improving the overall quality and we are reducing the amount of things that can (and will) go wrong.

We are also optimising on how we use our time, because we can just ignore what the automation is doing for us and focus on that something that really needs our attention.

Finally, in this modern and notification-based world, emails generate too much white noise to deal with. In this article, we will learn how to integrate SQL Server tasks’ notifications with one of the most used collaboration tools: Slack.

Keep in mind that this is not the only way to get this done. This guide would help you to better understand why we’re doing this (eventually why DevOps), and not strictly how to do it, even if we’ll see a real working example.

Minimal requirements

You need to setup an account on (on a paid plan) and a SQL Server edition. I recommend the free developer edition here.

Note: Don’t use SQL Server Express edition. This version doesn’t support any SQL Server Agent task as well as the Database Mail, which we’ll need hereafter. Also, about slack, you must create a paid account, because the integration described below will not work with a free profile.

In order to send emails, we will use an SMTP sever. It can be either a private Microsoft Exchange, PostFix, or any other on-premises solutions, together with a cloud delivery service, like SendGrid, SendInBlue, MailJet, or Office 365.

The scenario

In a team like mine, which uses chat as a daily communication driver, centralizing every business and technical message could be a great step forward for the members of the team in terms of awareness and knowledge sharing. Business roles can use that tool as well, so we can chat to each other switching topics between tech and functional discussions. It’s just a matter of how Slack (in our case) is configured with channels and naming conventions. A good setup helps us to better organize our meetings, small talks and any other topic related to implementations. This is a cool argument to speak about, but a little bit out of the scope of this guide. We will focus on notification bots instead.

SQL Server is able to send emails with its built-in features out-of-the-box, but we’d like to centralize every notification inside Slack, gaining the following advantages:

  • Instant notification
  • Tailored focus (custom sound instead the same popup for all the incoming emails)
  • Opt-out
  • Quickly involve people that are not following the channel by a mention
  • Relay the problem description within the chat
  • Take actions as soon as the notification is received

The proposed solution

Now, how can we send notifications from SQL Server in an easier way than using custom code or a Slack incoming webhook? Is there any integration or a Slack app?  Yes. And guess what? I think you’ll like it because you don’t need to write a single line of code, and you don’t need to choose between CLR, PowerShell or any other language. It’s ironic, but the integration is called “Email”.


The purpose of this article is just to describe Slack as a collaboration tool. Further details are provided here. As we said before, the following samples work only if you get a Slack account.

The Slack Email integration

This is the app to work with: Email. Its configuration is based on a four-step wizard:

  • Select the channel (or create a new one).


  • When added, set the name and a short description of the new contact (bot) in Slack.


  • Change the avatar (it’s important to recognize the bot at a glance)


  • After saving, copy the email address the app created for you.


A word about the “Hide this address” checkbox: this is useful if you want to hide the address to any other member of your workspace. You will be the only user able to read it if you check that box.

Type of SQL Server notifications and setup

As a DBA, we’re managing the following types of notifications on a daily basis:

  • SQL Server built-in and custom Alerts
  • Job execution status
  • Integration Services custom emails (within the packages)
  • External monitoring tools (which monitor SQL Instances)

With the exception of SSIS custom emails and external monitoring tools, everything is managed by Database Mail. This is a lightweight layer that allows us to send emails directly from a SQL Server Instance, connecting to a SMTP server.

To setup Database Mail you can follow this guide from Microsoft Documentation.

Once this is up and running, you can manage the notifications using SQL Server Operators. An operator is an alias managed by the SQL Server Agent which you can use to send emails and other types of messages, like pagers and Net Send.

Creating an operator is simple, just invoke the following system stored procedure:

USE msdb; 

EXEC dbo.sp_add_operator 
    @name = N'<name here>',
    @enabled = 1,
    @email_address = N'<email here>';

If you’re asking what email address you should use, it’s easy to say. You must fill the @email_address parameter with the address returned by the Email app integration for the channel you will send to ( in the example above). But, what about the name parameter? In my opinion, the best name is the one that helps us to understand where the message will be sent to. Suppose that we’d like to notify something about some index maintenance jobs. We could call the operator Slack Indexes Maintenance, Slack Indexes Maintenance Operator and so on. With such names, you will immediately know what we are going to send to Slack as the topic is related to index maintenance.

Thus, you’ll get the following snippet:

USE msdb; 

EXEC dbo.sp_add_operator 
    @name = N' Slack Indexes Maintenance Operator',
    @enabled = 1,
    @email_address = N'';


Slack channels naming considerations

I’d like to share with you my thought about the channel naming conventions. The principles to follow when naming channels, are:

  • Readability (clear for everyone)
  • Awareness (know what)
  • Style and Rules (know how)
  • Repeatability (keep using it from now on)

That being said, if the channel name describes a single action (like indexes maintenance in the above example) the operator which will send notifications should be unique. The reason is simple enough: we know that Indexes Maintenance Operator is sending messages to #sql-idx-maint-alerts (readability) and everyone knows that this is a one-to-one communication between a SQL Server Operator and Slack (awareness). Everyone knows that the “sql” channel prefix indicates SQL Server-related notification and the “alerts” suffix indicates that is an issue to pay attention to (style and rules). At the same time, everyone knows how to do the same with another pipeline of messages in the future (repeatability).

On the other hand, using a general purposes channel, like #sql-maint-alerts, allows us to be ready to future changes. Suppose that index maintenance will not be the only operation we’re executing in our servers (and typically isn’t). Does it make sense to create a new operator called for example, Database Concurrency Check Operator, which sends to a specific purpose channel? Clearly not.

In the end, a generic purpose channel gives the opportunity to hold more than one topic. All the notification sent to that channel should be, let’s say, of the same category to avoid too much generalization.

These solutions (one channel for more operators or a one-to-one solution) work equally well, it’s just a matter of how you’re designing your Slack channels. I suggest to avoid the “one channel to rule them all” pattern, because you’ll get thousands of mixed notifications without any clear idea behind them. After all, a noisy channel with messy content is something that will not be considered for a long time and will be eventually dropped.

Binding alerts

Alerts are triggers that communicate to an operator that something went wrong. This Brent Ozar’s article offers a good list of alerts that need attention. Here you can find their descriptions, based on severity. The binding is straightforward. All you need to do is to link the operator to the alert:


When one of those events occur, an operator is alerted. Then, it sends the message using its setup – in our scenario, an email. If the operator uses the Slack Email app, the email will be sent to the Email app, and the integration will redirect it to Slack.


Binding job execution statuses

Let’s see how we can use the notification mechanism to monitor SQL Server Agent Jobs. Each job lets you configure what to do in case of failure, success or completion of its execution. The binding is similar to the alert’s one:


Once the result is collected, based on the configurations you’ve set up, this job will send an email to the app.


Binding custom Integration services email

In order to send an email from a SQL Server Integration Services package (aka .dtsx) you need to configure the SMTP server within the package itself. This is a little out of scope, because it’s not really a SQL Server notification. You can leverage the power of SSIS and prepare a rich HTML-formatted message; the result is nice to read and informative like in these examples:


Cool stuff, isn’t it? It’s simply a .NET script in SSIS, which uses the System.Net namespace. Although the SSIS package is executed within a SQL Server Agent job, the default notification message that SQL generates is not easy to read. The message you always get is:

JOB RUN:<name> was run on <date/time> DURATION: x hours, y minutes, z seconds. STATUS: Failed. MESSAGES: The job failed. The Job was invoked by Schedule xyz (<name>). The last step to run was step xyz (<name>)


p style=”text-align:justify;”>Decorating the package with a more detailed email will improve the readability and the accuracy of our notifications.

Setup an external monitor for notifications to Slack

SQL Server is often (hopefully) monitored with specific counters. We’re using PRTG monitoring tool to measure them, and when a baseline changes and a threshold is hit, we send notifications to Slack. How? Again, sending to the Email app integration, specifying the right channel to send to and getting this:


The above report has been truncated. In a complete version of it, you’ll find the complete details of the measures, like the name of the servers, the sensors links, the grid with all the results, and everything you can see inside a PRTG admin portal.



Let’s see a more complete example, using a SQL Server alert. We’ll use the Severity 17 alert. Severity 17 is simple to raise and it describes a missing or insufficient resource when executing a command:

USE msdb; 

EXEC msdb.dbo.sp_add_alert @name=N'Severity 017',

Set the Response for the Severity 17 alert to “Notify Operator”, via email:


Run the following severity 17 based t-sql script:

RAISERROR(N'An error occurred Severity 17:insufficient resources!', 17, 1) 
WITH LOG; --don’t forget to use WITH LOG

Go to your Slack account. If you’ve configured everything correctly, you should see the following:


Did it work? Great! If not, continue reading.



If you don’t see the notification try these steps:

  1. Be sure that your Slack account is confirmed (its email too)
  2. Once the Slack account is confirmed, check if the channel still exists (CTRL+K -> name of the channel)
  3. Click on “Customize Slack” in the drop down menu of your Slack client/webpage, then click on Customize App in order to check whether the Email integration is active or not:



  • Verify Database Mail configuration (try to send the test email)
  • Verify the operator configuration (is it enabled?)
  • Verify the alert configuration (did you bind the response with email to the operator? Is it enabled?)
  • Verify the SQL Server Agent email profile configuration (is it enabled? Is it the right one?)



There are some disadvantages when using this kind of integration. For example, you cannot customize the message, unless you do it inside a .NET script. The Slack Email Address is publicly available, albeit hard to discover, so anyone can send message to your private slack channel by sending emails to that special address. Again, you cannot send the notification to more than one Slack channel or outside of the Slack world. In reality native SQL email notifications show the same limits, where email addresses of distribution lists are similar to Slack channels.

For our purposes, this is a very-low-effort automation with a high return in terms of value. With a couple of clicks, you can setup an email address representing a Slack channel, and, with little more, you can get notifications in a smart and comprehensive layout.

Everything is kept inside the collaboration chat tool we are using massively, every day. In the end, this example embeds one of the core DevOps principles (automation) and provides huge cross-role and cross-team value, especially when the channels include also network and server teams.

I hope that you’ll give this a try.

ALM DOs & DON’Ts – Definition of done

We all have been in this kind of situation: someone in the team states that a feature is done but in reality there is that little thing to figure out and the coding is completed the day after. Why is that? Because every person has a different definition of done inside his mind.
How can we protect a team from this? Simple! With a Definition of Done.


A good definition of done explicits what activities has to be done before declaring that our coding activites are over.
For example:

  • All unit tests are green
  • Coding style and conventions are respected
  • UI respects the specs validated by the Customer.

Every team and every project will create a different definition of done. The very important thing is that you and your team discuss such a definition to remove wrong expectaions about the status of work in progress.

Spazio… ultima frontiera…

Persone e Interazioni più che Processi e Tool”, il primo Valore è il punto di partenza di qualsiasi cambiamento che si ispiri all’Agile, Lean e DevOps, e sottende esplicitamente la necessità del cambiamento Culturale come aspetto portante.

Spesso però c’è un elemento che viene dimenticato o sottovalutato, ma che rappresenta un aspetto portante se si vuole promuovere la cultura Team basedalla base stessa dell’agilità: lo spazio fisico di lavoro.

Se ci si riflette per un momento, si riesce subito a capire come spazi adeguatisono essenziali per tutta una serie di motivi: dalla comunicazione diretta(come suggerito dai Principi), alla possibilità di avere i necessari Information Radiator, come la classica Kanban/Scrum Baord, che accompagnano il team nella visualizzazione e gestione dell’avanzamento delle attività.

Ogni team dovrebbe avere la propria area sufficientemente aperta, per comunicare trasparenza e disponibilità verso gli altri, e chiusa quanto basta, per garantire una condizione di privacy e generare il senso di appartenenzaal team.

In pratica, solo varcando la sogliadel working space del team possiamo conoscerlo realmente senza però trasformarci in ospiti indesiderati che vanno ad alterarne le dinamiche naturali.

L’importanza degli spazi è ben evidente in Lean, dove la tecnica/tool delle 5S (Seri, Seiton, Seiso, Seiketsu, Shitsuke) è tra quelle primarie, evidenziando come un’area di lavoro ordinata sia abilitante per poter lavorare in modo efficace ed efficiente. 

poster 5s leanproducts

In questo caso, però, la postazione è più intesa come scrivania personale di lavoro che come area del team. La connotazione più “Agile” è, invece, ben esplicitata in Disciplined Agile, rappresentando uno dei Goal della fase di Inceptiondi DAD: Form Work Environment.

dad goal form work environment

L’attenzione, però, non si limita ai soli ambienti fisici, ma si estende anche alla selezione dei tool e la creazione degli ambienti digitali di lavoro, aspetto fondamentale per introdurre un approccio che guarda a DevOps sin dall’inizio, andando ad abbracciarne le principali pratiche abilitanti come la Continuous Integration e Continuous Deploy o la creazione automatizzata di ambienti consistenti per il testing.

Interessante anche il concetto di “Tailor initial process”, recentemente aggiunto, che nella creazione degli ambienti tiene conto dello specifico lifecycle adottato e della relativa incidenza sul resto (principio “Choice is Good”) 

Tornando agli ambienti fisici, è fondamentale affidarsi ad esperti che vadano a studiare effettive soluzioni di riorganizzazione, tenendo anche conto di vincoli come, ad esempio, la sicurezza delle persone e gli spazi minimi individuali previsti per legge. Fondamentale è ricordarsi di creare, oltre alle aree dedicate ai team, le cosiddette Quite Room in cui potersi “ritirare” per fare delle riunioni che richiedono un isolamento completo e massima concentrazione.

Il tutto non deve mai portare alla creazione di enormi “pollai”, ovvero mega open-space con decine di persone in cui il caos comincerà a regnare sovrano non appena si inizierà a lavorare e comunicare.


Stay tuned J

Wrong version of ISDeploymentWizard in SSMS 17.8.1

The problem

Years ago, with SQL Server 2016 release, Microsoft came up with a separated brand new version of SQL Server Management Studio. It’s been a happy day for the SQL Server community and database developers.

Shortly afterwards, our company started to migrate every instances from older version of SQL Server to the 2016, using SSMS 17.*. Developers have already jumped into Visual Studio 2017 and everything seemed to work like a charm, until we started deploying integration services via the new SSMS, after we converted them to 2016 TargetServerVersion (which is NOT the Project Version).

The TargetServerVersion is the SSIS version, also for the deploy operations, while the Project Version setting tells to Visual Studio how to open projects based on .dtproj specifications on the XML projects definitions.

Some days ago I’ve realized that after updating to the latest build of SSMS (17.8.1), the .ispac deployment is actually executing the latest build of the Integration Services Deployment wizard (aka ISDeploymentWizard.exe). As a result every deploy of .ispac files, regardless trying double click or deploying directly from the Integration Services Catalog, the SSISDB, failed with one of the most scaring error message ever:

“[…] The Script Task <unique_name> uses version 15.0 script that is not supported in this release of Integration Services […]

What? Why? I’ve a workstation with SQL Server 2016 and the related Integration Services 13.0:


The computer I’m speaking of has the same build of mine, nobody has installed any other Integration Services versions anywhere. Andy Leonard explained this behavior in this blog post. Unfortunately, in my scenario, I cannot solve the problem.

Let’s try to explain better.


The workstation I’m working on has SQL Server 2016 (build 13.0.5149.0) and Integration Services 13.0 on Windows 10 Pro. I’ve got a simple package with a single script task which does literally anything:
blog_ssis_error_002bAs Andy suggested us, I’ve changed the TargetServerVersion to SQL Server 2016, so I’ve got C# 2015 compiler for scripts:

First execution and deploy

Executing it locally, nothing happens, but it happens in a green way (success):


Ok, now we’re going to deploy to the other machine, generating the .ispac file and double clickin on it. It’s important to make sure that you’re double-cliking the .ispac file. Do not right click on the Integration Service Catalog project folders because SSMS will execute the latest build of ISDeploymentWizard.exe by design.


deploy from SSMS 17.8.1


When double clicking, the app selector should use the version related to the TargetServerVersion setting of the .ispac. This works for many of my other computers. But for one of them, here is the screen:


double click on .ispac file

Hey! This is 2017 also when clicking on .ispac file. Let’s try to deploy using the new tool. The deploy succeeded.


And now, let’s try to validate the package execution via SSISDB, right clicking on the project itself and selecting “Validate…”. This is the result of the empty script package validation:


I’ve tried on six different machines, five ran successfully and ONLY ONE returned the above error message. Still stuck in the middle.

What have we changed?

Just the setup of SSMS (17.8.1) updating the 17.7 one. Once again, the same setup on all six machines. Five by six worked, this one is trying to kill me.

For some strange reason, something (I assure you all, not someone) has changed the registry in the .ispac application association, maybe when double clicking for the first time the file in a pending reboot (?). We’re still investigating, since we used to avoid any change in production without permissions and processes. That said, it’s weird. And it was so difficult to get.


Easy to say, now that we’ve figured out the root consequence. Not so good, but changing the registry on the key HKEY_CLASSES_ROOT.ispac with the 130 executable (IntegrationServices.ProjectDeploymentFile.130) fixed the unwanted behavior. The key has been set to IntegrationServices.ProjectDeploymentFile.140 right after the update from 17.7 and 17.8.1.

Instead of changing it via regedit, you can try an “open with…” with “use default” checked in order to force the association between .ispac file and the right ISDeploymentWizard.exe version. But this time, in this machine, it didn’t work. This is the reason why I tried the regedit action.


I have to say a big thanks to Andrea Amantini, one of my peer, which is well known for his ability to find out “a needle in a haystack.”. Strange things happened here. A combination of Murphy’s law, a sort of “black” friday and a pending reboot. Hopefully this helps someone, at least.

How to release a hotfix with pull-request inside VSTS in 3 steps

We all know the situation: the customer finds a critical bug in the latest release and he wants us to release a new version of our application with a fix. How do we handle this situation without breaking our team policies? How to release a specific fix to avoid regression problems?

First we need to fix that bug with the classical approach of feature-branches. We create a branch, fix the bug, create a pull-request and the team approves. These activities are set at the highest priority because a customer is in trouble and we must help.

Now we are in a situation where we have a specific commit that solves a specific problem with only the necessary lines of code modified.


Our target is to ship that specific commit that fixes that specific bug with a standard pull-request, without all the other work done in the development branch since the latest release. So we write down (in our clipboard for example) the id of the commit.


What can we do now to release?

1. New branch

We create a new branch.

git checkout -b my-hotifx

Now we fetch the latest updates from the remote repo.

git fetch origin

Then we set our branch my-hotfix to point to the latest commit of the remote release branch.

git reset --hard origin/release


2. Cherry-pick

Now we cherry-pick the specific commit we want to apply to the release branch without commiting (–no-commit option). We choose the no-commit option to carefully inspect what is going on in our files. It’s here where we use the commit id we saved early.

git cherry-pick <commit-hash> --no-commit

We verify that everything is fine (where fine depends on your specific project). Now we can commit and push to VSTS.

git add .
git commit -m "Hotfix"
git push origin mybranch:mybranch


3. Open pull-request

Our branch is now on the remote repo and we can open the pull-request with VSTS.


From here the team can approve the PR and fire up our automated release process that activates our automated test and if everything is fine we deploy safely.


With this blog post we explored the critical situation to release a hotfix without breaking the rules or taking shortcuts to avoid our release pipeline. As engineers we must maintain a cold approach even in hot situation and rely on our best practices. Human errors are always possible in particular when we’re stressed and a customer is making our phones hot.

ALM DOs and DON’Ts – Unit test

A unit test is a runnable piece of code that verifies that another piece of code (called production code) does what it is supposed to do.

A unit test has many characteristics and one of the most important is that a single unit test must verify one and only one thing.
If a unit test specifies more than one behavior things became harder to mantain. One a tests fail it has to be easy to understand what is going wrong and which section of our production code is behaving badly.


As a best practice we make each test independent to all the others: any given behaviour should be specified in one and only one test. Otherwise if you later change that behaviour, you’ll have to change multiple tests.


ALM DOs & DON’Ts – Database source control

Every application needs to store its data. A (relational) database is the most common choice in many situations. Like every other component of our software project, a database schema must be managed with a version control system. We will never work without source control for our source code files and we must use the same mindset when dealing with a db.


The database is a critical part of our application. If we deploy version 2.0 of our application against version 1.0 of our database, what do we get? A broken application. And that’s why our database should always be under source control right next to our application code.


ALM DOs & DON’Ts – Database source control

Every application needs to store its data. A (relational) database is the most common choice in many situations. Like every other component of our software project, a database schema must be managed with a version control system. We will never work without source control for our source code files and we must use the same mindset when dealing with a db.


The database is a critical part of our application. If we deploy version 2.0 of our application against version 1.0 of our database, what do we get? A broken application. And that’s why our database should always be under source control right next to our application code.


ALM DOs and DON’Ts – CI builds status

We all know the practice of continuos integration.

One of the common pitfalls about CI is that the build status is not monitored and not treated as one of the top priorities for the team.


A healty/green status of our CI process means that ore code is in a good shape for what our automated tests can tell. Fixing the build status ASAP is easier than leave it red and fix later because the recent changes of the codebase are vivid in the team members’ memory.

Un Leader non è per sempre… meglio non essere Chief di se stessi

Devo ammetterlo: non riesco a trattenermi dal sospirare ogni qual volta, in una organizzazione che si ispira all’Agile, incontro qualcuno che aggiunge ai ruoli specifici il suffisso “Chief”, trasformando di fatto quel ruolo in una posizione di implicito comando.
Se ho la fortuna di lavorare con persone che amano mettersi in gioco, e sono predisposte nello sfruttare l’ironia come strumento di crescita, spesso scherzo evidenziando come “Chief” mi ricordi il noto detersivo,

cif spruzzatore

e di come, tale suffisso, potrebbe indicare, in chiave Lean (DevOps), una persona che ispirandosi alle 5S e al concetto di Servant Leader, si occupi di pulire la scrivania dei propri colleghi per aiutarli a migliorare la propria organizzazione locale. Di certo non è il “capo”!

poster 5s leanproducts

Le 5S di Lean

Al di la del “suffisso” (che potrebbe essere anche “chief”, vista l’implicita accettazione che ormai gli si associa), è innegabile che una visione complessiva di un’azienda in chiave Lean/Agile richieda l’aggiunta di diversi ruoli di coordinamento, ma la loro “istituzione”, se avviene a freddo e senza coinvolgimento dal basso, rischia di trasformarsi in una nuova piramide organizzativain cui c’è un “capo” che da degli “ordini” espliciti ai subalterni, piuttosto che un Leaderin grado di ascoltare, risolvere le problematiche e guidare, quando necessario, le Persone con autorevolezza e raramente (se dicessi “mai” sarei poco realista) con autorità.

La questione, chiaramente, è riuscire a coltivare delle Persone che sviluppino le caratteristiche primarie di un Leader, riassunte nell’esplicita infografica di Alessandro Ferrari, andando al di là del titolo assegnato e dell’atteggiamento di aver raggiunto una “posizione” di comando sugli altri.

leader infografica

Un’azienda che ha la bravura, e un pizzico di fortuna, di far crescere i propri Leader, non ha bisogno di assegnargli titoli che richiamino il “comando”, perché queste Persone sono implicitamente riconosciute al suo interno come “trascinatori”, contemplando il fatto che ogni membro dell’organizzazione può diventare Leader in qualsiasi momento, catalizzando l’attenzione dei propri colleghi.  

Ciò, ovviamente, implica che un “Leader non è per sempre” solo perché è un “chief”, ma deve guadagnarsi tale riconoscimento giornalmente sul campo per non trasformarsi, nella migliore delle ipotesi, in “chief di se stessi”.

Stay tuned J