All notes

Provider-native doesn't have to mean developer-hostile

Provider-native architecture can preserve provider-specific identity, networking, data and security capabilities without exposing every cloud primitive to application teams. A platform can translate developer intent into precise, versioned and well-operated native implementations.

about 15 minutes min read

A developer needs a database.

The cloud provider offers an extensive API covering:

  • engine versions
  • instance classes
  • storage types
  • encryption keys
  • subnet groups
  • network controls
  • maintenance windows
  • backup retention
  • high-availability modes
  • deletion protection
  • monitoring integrations

One response is to expose all those fields directly:

database:
  engine: mysql
  engineVersion: "8.x"
  instanceClass: provider-specific-medium
  storageType: provider-specific-storage
  allocatedStorage: 100
  backupRetentionPeriod: 14
  publiclyAccessible: false
  deletionProtection: true
  subnetGroupName: bfstore-prod-database
  securityGroupIds:
    - sg-example

The developer has complete control.

They also need to understand the provider’s database service, network design, security model, backup behaviour and naming conventions before creating an ordinary application dependency.

Another response is to avoid the managed service entirely.

The organisation chooses a generic database deployment that can run in the same form everywhere.

The interface becomes simpler and more portable.

The platform team now owns:

  • database installation
  • patching
  • high availability
  • storage
  • backups
  • failover
  • upgrades
  • monitoring
  • recovery

The provider-native service has disappeared.

Its operational responsibilities have not.

There is a third option.

The platform can expose a smaller product contract:

apiVersion: platform.bfstore.dev/v1alpha1
kind: ServiceDatabase
metadata:
  name: catalog
spec:
  engine: mysql
  profile: transactional-v2
  environment: production
  availability: multi-zone
  recoveryTier: critical-v1

The implementation can still use the provider’s managed database service.

The application team chooses the properties that materially affect its service.

The platform owns the translation into provider-specific infrastructure.

Provider-native architecture does not require a provider-shaped developer experience.

The cloud API remains available to the engineers operating the platform.

Application teams use a product interface built around the outcomes they need.

Native capability and developer usability are not opposing choices.

They become compatible when the abstraction sits at the correct boundary and the promise behind it is precise.

Provider-native is an implementation choice

A platform abstraction is sometimes treated as concealment.

The argument goes:

The provider API is the real API.

Anything placed above it hides important detail.

The provider API is the implementation interface.

It does not follow that every developer should use it directly.

Most organisations already place layers above cloud APIs:

  • infrastructure modules
  • command-line tooling
  • policy checks
  • deployment pipelines
  • service templates
  • documentation

The question is not whether an abstraction exists.

The question is whether it is useful, accurate and operable.

DEVELOPER INTENT
       │
       ▼
PLATFORM PRODUCT
       │
       ▼
PROVIDER-NATIVE IMPLEMENTATION

A useful interface:

  • exposes meaningful choices
  • applies safe defaults
  • explains consequences
  • reports status
  • preserves ownership
  • allows deeper inspection

An unhelpful interface merely renames provider fields:

spec:
  cloudDatabaseSettings:
    providerDatabaseClass: medium
    providerSubnetGroup: private-data
    providerBackupWindow: "02:00-03:00"

The YAML belongs to the platform.

The cognitive load still belongs to the developer.

Build a versioned platform contract

A platform should abstract decisions, not vocabulary alone.

Suppose a provider offers six storage classes.

A developer requesting a transactional database may not care which product name is selected.

They may care about:

  • expected workload
  • availability
  • durability
  • recovery
  • cost
  • maintenance impact

The platform can expose those decisions through a product contract:

spec:
  profile: transactional-v2
  availability: multi-zone
  recoveryTier: critical-v1

The platform maps that request to native settings:

transactional-v2
multi-zone
critical-v1 recovery
        │
        ▼
provider database class
multi-zone topology
encrypted storage
backup retention
point-in-time recovery
deletion protection
monitoring

This is useful only when the profile means something precise.

For example:

Profile:
    transactional-v2

Availability:
    multi-zone

Recovery targets:
    RPO 15 minutes
    RTO 60 minutes

Backup retention:
    35 days

Last restore drill:
    2025-10-12

Demonstrated recovery:
    18-minute recovery-point gap
    52-minute recovery time

Known limits:
    one writable primary
    regional dependency

Not every property needs to appear in the developer’s request.

It should be available through documentation, status or the operating view.

The platform interface may be small, but the promise behind each field must be precise, versioned and testable.

Profiles need lifecycle rules

A profile is an organisational API.

Its implementation will change.

Suppose transactional-v2 moves to a new storage model or provider service.

That change might cause:

  • replacement
  • downtime
  • cost increase
  • changed recovery behaviour
  • migration risk

The platform should therefore define:

  • profile version
  • upgrade policy
  • migration impact
  • deprecation period
  • whether changes apply to existing resources
  • how users accept breaking changes

A profile should not silently become a different product while retaining the same name.

Safe defaults should remain ordinary

A developer requesting object storage should not need to remember:

  • block public access
  • enable encryption
  • add ownership metadata
  • configure lifecycle policy
  • enable audit events
  • choose an approved region

The platform can apply those decisions automatically:

apiVersion: platform.bfstore.dev/v1alpha1
kind: ObjectStore
metadata:
  name: product-images
spec:
  profile: application-assets-v1
  environment: production

The native implementation may include:

public access:
    blocked

encryption:
    enabled

ownership:
    catalog-team

lifecycle:
    application-assets-v1

audit:
    enabled

placement:
    approved production region

A policy boundary can reject attempts to weaken mandatory controls.

This is not hiding security.

It is making security the ordinary result.

Preserve the native capabilities that improve the outcome

Provider-managed services can remove operational work the organisation would otherwise perform itself.

For a managed database, that may include:

  • infrastructure replacement
  • automated backups
  • maintenance orchestration
  • replication
  • failover mechanisms
  • service monitoring
  • control-plane integration

The provider still introduces native limits and failure modes:

  • quotas
  • regional availability
  • maintenance behaviour
  • control-plane outages
  • service deprecation
  • proprietary recovery paths
  • pricing constraints

The platform contract should either absorb those differences or expose the consequences that matter.

Managed does not mean ownerless.

CLOUD PROVIDER

operates underlying service machinery


PLATFORM TEAM

defines and operates the service product


APPLICATION TEAM

uses the capability correctly
and owns service behaviour and data

Native identity can improve the experience

A supposedly portable approach may distribute:

access key

secret key

to applications in every cloud.

The configuration looks consistent.

The operating model is weak.

Applications and teams now need to manage secret storage, rotation, expiry, copying, revocation and accidental exposure.

A provider-native workload identity model can issue temporary, scoped credentials based on runtime identity.

The platform can offer a consistent request:

cloudAccess:
  - capability: object-read
    resource: product-images

The implementation translates this into the provider’s native trust and permission model.

The developer outcome remains understandable:

This service may read
the product-images resource.

Its authority is temporary.

No static cloud credential
is stored in application configuration.

This creates platform-level consistency in how authority is requested and governed.

It does not necessarily make application code portable.

PLATFORM PORTABILITY

consistent request, provisioning
and governance model


APPLICATION PORTABILITY

the same application API and code
work across implementations

A service may still use provider-specific SDKs, data semantics or failure behaviour.

The platform should promise only the portability it actually delivers.

Network abstractions should describe reach

Application teams do not need to assemble virtual networks, route tables, firewalls and private endpoints directly.

They do need to express communication intent.

network:
  exposure: internal
  dependencies:
    - name: catalog-database
      protocol: mysql
      direction: outbound
    - name: telemetry
      protocol: otlp
      direction: outbound
  egressProfile: restricted-v1

The contract may also need to describe:

  • cross-region communication
  • data classification
  • public fallback
  • tolerated dependency failure

The platform translates the intent into native routing, firewall policy, endpoints and DNS.

The abstraction should explain the resulting behaviour:

  • the service is not publicly reachable
  • only approved dependencies can be contacted
  • outbound internet access is restricted
  • denied communication leaves evidence

The developer should understand the network contract.

They should not need to choose every route-table entry.

Abstraction must remain inspectable during failure

A platform becomes unhelpful when it hides everything behind:

The platform handles it.

Provider-native implementation should remain visible in layers.

Product view

ServiceDatabase:
    catalog

Profile:
    transactional-v2

Availability:
    multi-zone

Status:
    ready

Operating view

Private:
    yes

Encrypted:
    yes

Recovery target:
    critical-v1

Last restore drill:
    2025-10-12

Demonstrated recovery time:
    52 minutes

Implementation view

Cloud:
    AWS

Region:
    eu-west-2

Native resource:
    managed relational database

Composition:
    service-database-aws-v3

Diagnostic view

Authorised operators can access:

  • provider resource identifiers
  • native events
  • network configuration
  • service logs
  • provider-specific failure details
SIMPLE USER INTERFACE
         │
         ▼
OPERATING PROPERTIES
         │
         ▼
NATIVE IMPLEMENTATION
         │
         ▼
DETAILED DIAGNOSTICS

Abstraction reduces the starting depth.

It does not need to destroy the ladder.

Status should translate without pretending certainty

Provider APIs return errors shaped around their own resource model.

A platform request may fail because:

  • quota is exhausted
  • a region lacks capacity
  • an identity lacks permission
  • a dependency is missing
  • a selected feature is unavailable

Weak status:

Error:
    InvalidParameterCombination

Stronger status:

State:
    blocked

Capability:
    ServiceDatabase

Reason:
    requested multi-zone capacity
    is temporarily unavailable
    in the selected region

Action:
    platform retrying automatically

Owner:
    platform-database

The native error should remain attached for diagnosis.

Some provider failures will not translate cleanly.

In that case, the platform should say so:

State:
    blocked

Impact:
    database provisioning cannot continue

Reason:
    unknown provider failure

Correlation:
    req-18472

Owner:
    platform-database investigating

Translation should add meaning without hiding uncertainty.

Developer experience includes the failure path

A platform may make creation delightfully simple:

Create database:
    one form

Then failure requires:

open cloud console

find native resource

identify account

search provider logs

decode error

message platform team

The happy path is abstracted.

The failure path is provider-hostile.

A complete platform product should provide:

  • visible progress
  • translated status
  • correlation identifiers
  • relevant logs
  • retry information
  • remediation
  • ownership
  • escalation

Developers should not need a cloud archaeology qualification to understand whether the platform is retrying or waiting for their action.

Make limits and alternatives explicit

A product interface cannot support every provider feature.

Specialised needs should leave the standard path deliberately.

Additional product tier

A recurring need becomes a supported profile:

availability: regional-critical-v1

Provider-specific product

A workload deliberately selects a native capability:

kind: AwsStreamingAnalytics

Governed override

An authorised user changes a narrow implementation property:

maintenance:
  window: sunday-morning

Overrides should be:

  • typed
  • narrowly scoped
  • validated
  • auditable
  • visible in support status
  • promoted into product fields when they recur

A generic provider-settings map recreates the raw API through a side door.

Fully custom path

A team owns a specialised implementation outside the standard platform product.

STANDARD PATH

platform owns implementation


EXTENDED PATH

shared ownership


CUSTOM PATH

workload team owns more
provider-specific operation

The platform should distinguish:

unsupported

from:

forbidden

and:

supported through a different product

Portability should name the required property

Using a provider-native service creates dependency.

That dependency should be understood rather than denied.

“Portable” may refer to different things:

DATA PORTABILITY

Can state be exported
in a usable format?


APPLICATION PORTABILITY

Can the application use
another implementation?


CONTROL-PLANE PORTABILITY

Can the capability be provisioned
through another provider?


OPERATIONAL PORTABILITY

Can teams monitor, recover
and support the replacement?


IDENTITY AND NETWORK PORTABILITY

Can trust and communication
be rebuilt safely?

Not every capability needs every form of portability.

For each product, the platform can record:

  • provider
  • data format
  • export path
  • migration constraints
  • required movement time
  • tested recovery route
  • criticality
  • exit-plan level

Provider native does not have to mean permanently trapped.

It means portability is designed and tested at the level justified by the service.

Ownership and expertise make the abstraction credible

Provider documentation explains the underlying service.

Platform documentation should explain the organisational product:

  • who should use it
  • which profiles exist
  • what each version promises
  • which limits apply
  • how credentials are delivered
  • how cost changes
  • who owns failure
  • which provider-specific differences remain
  • how upgrades and exits work

The platform should link to native documentation where deeper provider behaviour matters.

PLATFORM DOCUMENTATION

how our product behaves


PROVIDER DOCUMENTATION

how the managed service works

Both are useful.

They answer questions at different layers.

The platform team still needs native expertise.

Somebody must understand provider identity, lifecycle, networking, quotas, pricing, backup behaviour, failure modes and upgrade paths.

APPLICATION TEAM

understands the platform contract


PLATFORM TEAM

understands the product
and its native implementation

A thin layer over a poorly understood cloud service is not a platform product.

It is a confidence wrapper.

The contract becomes trustworthy when its owners test the promises it makes.

A bfstore provider-native path

Suppose the bfstore review service needs:

  • a MySQL database
  • Kafka access
  • private networking
  • workload identity
  • telemetry

The application declaration may be:

apiVersion: platform.bfstore.dev/v1alpha1
kind: Application
metadata:
  name: review-service
spec:
  runtime: go
  protocol: grpc
  exposure: internal

  database:
    profile: transactional-mysql-v2
    availability: multi-zone
    recoveryTier: standard-v1

  messaging:
    consumes:
      - order.completed
    publishes:
      - review.submitted

  cloudAccess:
    - capability: review-storage-read

  network:
    dependencies:
      - name: review-database
        protocol: mysql
      - name: telemetry
        protocol: otlp

The AWS implementation may provide:

  • native workload identity
  • a managed MySQL service
  • private networking
  • provider-specific storage
  • cloud audit events
  • OpenTelemetry integration

An Azure or Google Cloud implementation may use a different resource graph.

The platform contract remains coherent, but not necessarily identical in every property.

The product should publish which promises are portable and which differences remain provider-specific.

REVIEW SERVICE INTENT
          │
          ▼
VERSIONED BFSTORE CONTRACT
          │
          ▼
AWS-NATIVE IMPLEMENTATION
          │
          ▼
VISIBLE STATUS AND EVIDENCE

No one needs to pretend the implementation is provider neutral.

The developer also does not need to assemble it manually.

Questions I now ask

Outcome

Which outcome does
the developer need?

Choice

Which decisions materially
affect the service?

Contract

What exact, versioned promise
does the platform make?

Native value

Which provider capability improves
security, reliability or operation?

Understanding

Can behaviour, cost, limits
and failure be understood?

Inspection

Can operators reach
the native evidence?

Escape

Which alternative path
and ownership model apply?

Portability

Which portability property
must be tested?

These questions separate a useful provider-native platform from a cloud console wearing a developer-portal hat.

The mental model I am keeping

My earlier model was:

PROVIDER NATIVE

developers use provider APIs directly

The stronger model is:

                         DEVELOPER INTENT
                                │
                                ▼
                    VERSIONED PLATFORM PRODUCT
                                │
              ┌─────────────────┼─────────────────┐
              │                 │                 │
              ▼                 ▼                 ▼
          SAFE DEFAULTS    MEANINGFUL CHOICES   GUARDRAILS
              │                 │                 │
              └─────────────────┼─────────────────┘
                                ▼
                    PROVIDER-NATIVE FULFILMENT
                                │
              ┌─────────────────┼─────────────────┐
              │                 │                 │
              ▼                 ▼                 ▼
           IDENTITY          NETWORK           DATA
              │                 │                 │
              └─────────────────┼─────────────────┘
                                ▼
                       STATUS AND EVIDENCE
                                │
                                ▼
                       TESTED PRODUCT PROMISE

Provider-native architecture becomes developer-hostile when the platform exposes raw cloud complexity without helping users make sense of it.

It can become equally hostile when an abstraction hides every consequence and turns failure into a support ticket.

The useful middle is a platform product that preserves native capability while translating it into:

  • meaningful choices
  • precise contracts
  • safe defaults
  • visible behaviour
  • understandable status
  • clear ownership

Developers do not need every provider field. They need a reliable way to request an outcome, understand its important properties and diagnose where the promise has failed.

The cloud-native implementation can remain rich.

The developer interface can remain small.

Those ideas are not in conflict.

The platform’s job is to build the bridge between them without painting over the signposts.