Northgate Platform Solutions

01 · The Power Apps SQL connector is not a database driver

SymptomQueries that worked in SSMS came back short, or not at all, from a code app.

What it turned out to beThe connector pages silently, so a read that looks complete may be the first page. In practice its filter tree gives out at roughly a hundred nodes, so a long IN list fails without a useful error. The data-source API gives you filter, order, top, skip and select and nothing server-side beyond that. Primary keys must be single-column, datetime literals in filters are unreliable, and one view built on CTEs and UNIONs would not bind as an app data source even though Power Automate read the same view without complaint.

What to doWalk every read on a keyset. Chunk IN lists into ten ORed comparisons. Aggregate client-side. Give the estimates table a surrogate identity key. Point the flows at the view and the app at base tables.

03 · What pay-as-you-go actually bills for a code app

SymptomNobody could say what the production app would cost once partners without premium licenses opened it.

What it turned out to beThe Power Apps per-app meter bills $10 per unique unlicensed user, per app, per month in a pay-as-you-go environment; anyone with a Power Apps licence or per-app pass never appears, and the meter is not specific to code apps. The only way to trust that is to prove it: one unlicensed test user, one launch per app, then read the next month's billing report and find exactly those rows.

What to doCreate the pay-as-you-go environments early, link the billing plan, run the one-user test before go-live, and write the reading-the-bill procedure down for finance.

04 · Code apps do not run in the Power Apps mobile player

SymptomThe phone experience everyone expected from canvas apps was simply absent.

What it turned out to beA code app is a web app inside the Power Apps player; the mobile app does not host it. The practical phone story is a managed web link, pushed by Intune, to the play URL with the navigation bar hidden. Then the usual mobile Safari rules apply: inputs under 16px zoom the page and never zoom back, and 100vh is wrong on iOS.

What to doShip an Intune web-link icon rendered from one master for both platforms' safe areas, use 16px inputs under pointer: coarse, and lay out with 100dvh.

05 · A code app cannot call a flow, so make the flow watch a table

SymptomThe app needed to send campaign email, and the SDK offered no Power Automate connector and no user token.

What it turned out to beThe SDK gives the app no Power Automate connector and no user token; calling Graph means bringing your own MSAL and app registration, and a custom connector around an HTTP-triggered flow is one more endpoint to secure and deploy per environment. The pattern that held up: the app writes a command row to a SharePoint list, a flow triggers on the row, and a daily engine reads a settings row for cadence.

What to doEvery send becomes a row first, which gives an audit trail for free. Put test mode in the settings row so every partner-facing send can be redirected to one inbox with a cap.

06 · Created By is always the service account

SymptomAn intake app could not tell who had submitted a request; every item said the same name.

What it turned out to beWhen a service account owns the connection, the system author on every item is the service account. The requester has to be captured deliberately in a person column, and users then have to be matched across UPN, SMTP address and bare login, because different columns store different forms of the same person.

What to doMake a Submitter person column the real key from day one, key duplicate checks off it rather than Created By, and migrate history with a scripted backfill that sets it.

07 · SharePoint column types have exact shapes

SymptomWrites succeeded with no error and the data was missing.

What it turned out to beChoice columns want an object, not a string; a string is dropped silently. Person columns want the full expanded user with a claims string. Flipping a person column to multi-select changes its shape from one record to a table and silently breaks every existing read and write in the app.

What to doTreat a silent write as a shape mismatch first. For the person-column change, add a new column, backfill it by script, and keep the old one as a fallback until nothing reads it.

08 · Row security in the app is not Dataverse security

SymptomA code app over a shared SQL connection needed partners to see only their own rows.

What it turned out to beAn implicitly shared SQL connection can be driven by any app user outside the app through the connector unless Secure implicit connections is on. Filtering by identity columns in the app is a visibility rule for low-sensitivity data, acceptable for projection figures behind an Entra group with on-behalf writes that re-check authority. It is not a security boundary. Anything that must hold against a determined user belongs in Dataverse security roles or a SQL view per role.

What to doSay which one you have, and turn on Secure implicit connections either way. If the data must be protected from a user who has the connection, put it on Dataverse and let the role do the work.

09 · Digests, time zones and the things workflow expressions do silently

SymptomA leadership digest missed records on Mondays and month boundaries.

What it turned out to beThe 'since last run' cut compared a local timestamp with UTC. Separately, numerics from SQL arrive as strings in flow expressions and comparisons fail quietly unless cast, sort() breaks on mixed types, and inline images as cid attachments failed in the branded template.

What to doConvert explicitly to Eastern, use a 72-hour window on Mondays, float() every SQL numeric, and order server-side. For the icon, test each mail client in use: classic Outlook strips data-URI images, so a hosted image URL is the safer default.

10 · One app registration, two identities, nothing it does not need

SymptomMigration scripts and a Power BI permission audit both needed to authenticate without a person present.

What it turned out to beDelegated, with Sites.ReadWrite.All and the Graph user and group read scopes, the registration signs in PnP PowerShell for migrations and backfills: it can create, update and delete items, and the tenant denies it list and column creation even for a site owner. As a service principal with a secret it holds only read application permissions and runs the Power BI scanner APIs plus Graph transitive membership so every group becomes people; the scanner access is granted by the Fabric tenant setting for a security group, not by a scope.

What to doCreate lists and columns in the UI and let scripts fill them. Put the Fabric admin setting and the Graph application permission through a formal change request. A leaked secret then cannot restructure a site.

11 · The tenant with no data policy

SymptomAn audit of what was actually enforced found no DLP policies at all.

What it turned out to beThis is common in estates that grew one app at a time. The first policy is simple to design and dangerous to apply: Microsoft 365 connectors in Business, consumer and unmanaged connectors Blocked where the platform allows it, and the SQL Server connector endpoint-filtered to the gateway's servers. Any app that mixes groups breaks the moment the policy saves.

What to doAudit first, document the gap, draft the policy, and check impact in the admin center before saving. Then fix the mixed apps, then apply.

12 · Usage telemetry the platform does not give you

SymptomThe built-in analytics could not say who opened a code app, or from what device.

What it turned out to beApplication Insights is the usual answer for a single-page app; with no Azure subscription in scope, the app logs its own sessions to a SharePoint list instead: launch, landing, screen opened and estimate written, with device class, operating system, browser, viewport, entry point (icon, email, digest, direct), build stamp and the platform's time-to-interactive. Labels only, never a figure. Writes are fire-and-forget; a failure is swallowed so nothing on the user's path waits on the log.

What to doFlag it per environment so the same source stays silent in production until the people being logged have been told. Exclude simulated sessions from every count.

Hit one of these?

Most of them take an afternoon to fix once you know what you are looking at. Write and say which one.

darwin@northgateplatform.com