CertSafari
    Snowflake SnowPro Specialty: Native Apps· Lessons

    Domain 2 · Lesson 3/12

    Native App Package Anatomy: Manifest, Setup Script and Versioned Schemas

    Given a use case, build Native App Framework components.

    16 min read
    9.5% of exam
    7 sources
    Published 5 Oct 2026
    Docs as of 4 Oct 2026

    What you will be able to do

    • Describe what an application package contains and where the manifest and setup script must live
    • Choose between manifest_version 1 and 2, and explain what consumers agree to under version 2
    • Write a setup script that runs safely more than once and respects the setup script's restrictions
    • Decide whether an app object belongs in a versioned schema or a regular schema
    • Evolve stateful objects such as configuration tables across upgrades without losing data
    • Declare the privileges, images and endpoint that a container-based app needs in its manifest, and place its objects in a regular schema
    • Decide which data to include in an application package, and expose it to the app through grants, proxy views and application roles

    Key concept

    Application package — The provider-side container that holds a Native App's logic and data content, plus its versions and patches. Every version brings its own manifest.yml and SQL setup script, and the setup script builds the app's objects inside the consumer's application object.

    1.The application package and its manifest

    An application package is the provider-side container for a Snowflake Native App. It holds the app's data content and application logic, plus the versions and patches defined for the app. Each version needs two files of its own: a manifest file and a setup script. You can create the package before either file exists, but you cannot develop or test the app until both are uploaded to a stage the package can read.

    The manifest has strict placement rules. The file must be named manifest.yml, it must be uploaded to a named stage, and it must sit at the root of the directory structure on that stage, next to the other application files. The manifest gives the location of the setup script, defines the version, and holds configuration for the app. Under artifacts it lists things such as the readme, the setup script and, for apps with containers, the container images. Under privileges it lists what the app asks the consumer for.

    A version 2 manifest that names its artifacts and requests privileges for automated grantingyaml
    manifest_version: 2
    version:
      name: v1
    artifacts:
      readme: readme.md
      setup_script: setup.sql
    privileges:
      - CREATE TABLE:
        description: "Allows the app to create tables in the consumer account"
      - CREATE WAREHOUSE:
        description: "Allows the app to create warehouses in the consumer account"

    The manifest_version field decides which manifest format applies. Version 1 supports the current and legacy functionality of Native Apps. Version 2 adds more features, the main one being automated granting of privileges. In the example above, Snowflake automatically grants CREATE TABLE and CREATE WAREHOUSE when the app is installed. This changes what the consumer is agreeing to. During installation Snowsight shows the requested privileges, and by installing, the consumer accepts that the app can be granted these privileges during later upgrades without being asked again. Consumers who want limits can create feature policies that restrict which objects an app is allowed to create.

    Checkpoint 1 of 7· Check yourself

    A provider moves an app's manifest from manifest_version: 1 to manifest_version: 2 and lists CREATE TABLE under privileges. What does a consumer accept by installing the app?

    A container-based app (Snowpark Container Services) adds its own entries to the same manifest. Its architecture has three parts that the manifest must declare:

    - Images. Add an images property under artifacts.container_services, with one entry for each image. Each path names the database, schema and image repository that hold the image. - Compute and network privileges. CREATE COMPUTE POOL lets the app create a compute pool in the consumer account. You do not need it if the consumer creates the pool manually. BIND SERVICE ENDPOINT lets an endpoint be reached from outside Snowflake. These are the compute pool and service endpoint binding requirements. - A user interface endpoint. The optional default_web_endpoint names a service and an endpoint, and that endpoint must also be defined in the service specification file. You can specify only one of default_web_endpoint and default_streamlit.

    The manifest reference also requires a grant_callback in the configuration block for an app with containers. It is a stored procedure that can create compute pools, services and perform other setup tasks.

    Objects for the containers must not live in a versioned schema. Snowpark Container Services is not supported there, so create the services and compute pools in a regular schema. Setup-script logic that builds them runs inside the consumer's account, which is why the manifest-first approach to sharing content does not apply to them.

    Privileges a container-based app requestsyaml
    privileges:
    - CREATE COMPUTE POOL:
      description: 'Required to allow the app to create a compute pool in the consumer account.'
    - BIND SERVICE ENDPOINT:
      description: 'Required to allow endpoints to be externally accessible.'
    The web endpoint that serves the app's user interfaceyaml
    default_web_endpoint:
      service: ux_schema.ux_service
      endpoint: ui

    Checkpoint 2 of 7· Check yourself

    A container-based app must expose its web UI endpoint outside Snowflake. Which manifest privilege does the app need for that?

    Sources1234

    2.The setup script: SQL only, internal by default

    The setup script runs when a consumer installs or upgrades the app, and when a provider creates or upgrades an app to test the package. It is SQL only, so no other language is supported for the script itself. It creates everything the app needs: database objects, stored procedures, views and application roles.

    Privacy is the default. Database objects created by the setup script are internal to the app, and a consumer cannot see or access them directly unless the provider exposes them, usually through application roles. A table that the provider never grants on stays hidden from the consumer.

    Some statements are not allowed in a setup script: USE DATABASE, USE SCHEMA, USE ROLE and USE SECONDARY ROLES. You also cannot create or call procedures that are EXECUTE AS CALLER, or run code that is not included in the application package. Because the session context cannot be switched, every object must be qualified with its schema:

    CREATE SCHEMA does not switch context, so the table is schema-qualifiedsql
    CREATE SCHEMA IF NOT EXISTS app_config;
    CREATE TABLE IF NOT EXISTS app_config.params(...);

    For large apps, the manifest points to one primary setup script, which pulls in secondary scripts with EXECUTE IMMEDIATE FROM. These run in the order they appear, and the paths are case-sensitive. A leading / means the app root, ./ means the current script's directory, and ../ means its parent. At app runtime, only the / form is allowed. Event logging is not supported in scripts called this way.

    The main design rule is that the script must be safe to run again. It can run multiple times during installation and upgrade, for example when a failed run is retried. That is why Snowflake recommends CREATE OR REPLACE or CREATE IF NOT EXISTS. CREATE OR REPLACE has a catch: replacing a procedure silently removes the grants on it. If the script fails before it re-grants, consumers lose access until a new version or patch restores the grant.

    Checkpoint 3 of 7· Check yourself

    A provider adds a table to the setup script but never creates a view over it or grants on it to an application role. What can a consumer who installs the app do with that table?

    Checkpoint 4 of 7· Exam question

    A provider's Native App writes a row to a table every time a consumer performs an action, for compliance auditing. These rows must remain intact and unaffected when the app is upgraded to a new version. In which schema type should this table be created, and why?

    Sources5

    3.Versioned schemas versus regular schemas

    Every app object falls into one of two groups. Stateless objects are the app's code: stored procedures, UDFs, Streamlit apps and similar. They only need to exist for the life of a version and can be recreated each time. Stateful objects, such as a configuration table in the consumer account, must keep their contents across versions.

    Versioned schemas exist for the stateless group. A versioned schema works like a regular schema but internally holds a subschema for each app version. That gives version pinning: a query started by a v1 object stays tied to v1 even after an upgrade. Consumers see only the objects for the version they have installed, even in SHOW OBJECTS. Versioned schemas can only be created inside the setup script, within an application object.

    This extra machinery means many object types are not compatible with versioned schemas. Snowpark Container Services, tasks, tags, masking policies, and grants or future grants are all unsupported. A versioned schema cannot be cloned or used as a clone target, and it cannot be dropped, because dropping it would remove every version's objects, including ones that older queries are still using.

    Where each kind of app object belongs
    ObjectSchema typeReason
    Stored procedures, UDFs, Streamlit appsVersioned schemaStateless code, recreated per version or patch
    Configuration tableRegular schemaContents must survive upgrades
    Application roles, tasks, tags, masking policiesRegular schemaNot supported in versioned schemas
    Snowpark Container Services objectsRegular schemaNot supported in versioned schemas

    Checkpoint 5 of 7· Match them up

    Match each object to the schema type it belongs in, or the rule that applies

    Tap a term, then the definition that fits it.

    Sources4

    4.Managing schema changes across upgrades

    Since every version has its own setup script, each script has to handle a fresh install and an upgrade from the previous version. For versioned schemas, always use CREATE OR ALTER VERSIONED SCHEMA so the schema stays compatible across versions and patches. Objects inside it must be recreated with CREATE OR REPLACE or CREATE IF NOT EXISTS, because each version has its own copies in the schema's subschemas. Objects in versioned and non-versioned schemas can reference each other.

    For stateful objects in a regular schema, create them only if they are missing, then apply changes additively. The documented pattern below does both: on a fresh install the CREATE builds the full table, and on an upgrade the ALTER adds the column the older version lacked. Existing data is kept either way.

    A stateful configuration table that works for both first install and upgradesql
    CREATE SCHEMA IF NOT EXISTS stateful_object;
    
    CREATE TABLE IF NOT EXISTS stateful_object.config (
      config_param STRING,
      config_value STRING,
      default_value STRING,
      modified_on  TIMESTAMP);
    
    ALTER TABLE stateful_object.config
      ADD COLUMN IF NOT EXISTS modified_on TIMESTAMP;

    Checkpoint 6 of 7· Fill the gap

    Which keyword completes the recommended statement for creating the schema that holds an app's stateless code?

    CREATE OR ALTER  ?  SCHEMA version_schema;

    Sources4

    5.Bundling data in the package and sharing it with the app

    An application package can bundle data content next to the app's logic. This is a data inclusion decision, and there are three options:

    - Put the data in the package. Create the schema and table in the application package, then grant USAGE on the schema and SELECT on the table TO SHARE IN APPLICATION PACKAGE. - Reference data that stays outside the package. You cannot share objects outside the package directly with the installed app. Grant REFERENCE_USAGE on the other database to the share in the package, then create a view in the package over the external object. - Create the object in the setup script. It is then internal to the app, and the consumer cannot reach it unless you expose it.

    This is the boundary between shared data and private data. Anything you add to the package is private to the package and not visible when the app is installed until you grant on it to the share. When you share an object you must also share its schema.

    Sharing with the app is still not the same as exposing data to the consumer. To let consumers read shared content, the setup script creates a view in a versioned schema and grants privileges on it to an application role. Each version then holds only its own view definition, which suits upgrades. Snowflake also recommends defining policies on these proxy views, so the policies cannot be changed after installation.

    The manifest can also declare shared content in a shared_content section. Snowflake says this is the recommended way to share content, and a setup script should be used only for advanced scenarios that run code in the consumer account. Each patch uses either grant-based or declarative sharing, never both.

    Share a package-resident table with the appsql
    GRANT USAGE ON SCHEMA app_package.shared_schema
      TO SHARE IN APPLICATION PACKAGE app_package;
    GRANT SELECT ON TABLE app_package.shared_schema.shared_table
      TO SHARE IN APPLICATION PACKAGE app_package;
    Expose shared data to consumers through a view and an application rolesql
    CREATE APPLICATION ROLE app_user;
    
    CREATE OR ALTER VERSIONED SCHEMA inst_schema;
    GRANT USAGE ON SCHEMA inst_schema
      TO APPLICATION ROLE app_user;
    
    CREATE VIEW IF NOT EXISTS inst_schema.shared_view
      AS SELECT c1, c2, c3, c4
      FROM shared_schema.shared_table;
    
    GRANT SELECT ON VIEW inst_schema.shared_view
      TO APPLICATION ROLE app_user;

    Checkpoint 7 of 7· Check yourself

    A provider's table lives in other_db, outside the application package. How do they make it available to the app?

    Sources67

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 1.The setup script can be written in Python or Java, like the app's stored procedures.Why is that wrong?

      Only the setup script is limited to SQL. Procedures and UDFs can use other languages, but the setup script that creates them is plain SQL.

      Covered in The setup script: SQL only, internal by default

    2. 2.Every app object should go in a versioned schema so it is version-pinned.Why is that wrong?

      Only stateless objects belong in versioned schemas. Stateful objects such as configuration tables, and unsupported types such as tasks and application roles, go in regular schemas.

      Covered in Versioned schemas versus regular schemas

    3. 3.A container-based app's services should be created in a versioned schema like the rest of its code.Why is that wrong?

      Snowpark Container Services is not supported in versioned schemas, so those objects go in a regular schema.

      Covered in The application package and its manifest

    4. 4.A provider can grant an installed app access to a table in another database directly.Why is that wrong?

      Objects outside the application package cannot be shared directly with the installed app. The provider needs REFERENCE_USAGE plus a view in the package.

      Covered in Bundling data in the package and sharing it with the app

    Sources

    Every claim above is drawn from one of these pages, quoted as it was written on the date shown.

    1. 1.
      “The manifest file must exist at the root of the directory structure on the named stage where other application files are stored.”
      ↩︎ The application package and its manifest
      “This version of the manifest file provides support for additional features, including automated granting of privileges.”
      ↩︎ The application package and its manifest
      “To specify the location of the container images used by the app with containers, add the images property to the artifacts.container_services block.”
      ↩︎ The application package and its manifest
      “Only one of the default_web_endpoint and default_streamlit can be specified.”
      ↩︎ The application package and its manifest
      “they agree that the app may be granted these privileges during upgrades without requiring additional consent.”
      ↩︎ Checkpoint
      “This privilege is required to allow an endpoint to be accessible outside of Snowflake.”
      ↩︎ Checkpoint
    2. 2.
      “Each version of an app requires its own version of the manifest and setup script”
      ↩︎ The application package and its manifest
      “An application package is a container that encapsulates the data content and application logic used by a Snowflake Native App.”
      ↩︎ Key concept
    3. 3.
      “The callback function is a stored procedure that can create compute pools, services, and perform other setup tasks required by the application.”
      ↩︎ The application package and its manifest
    4. 4.
      “Snowpark Container Services is not supported in versioned schemas.”
      ↩︎ The application package and its manifest
      “Stateless objects should be created in a versioned schema.”
      ↩︎ Versioned schemas versus regular schemas
      “A consumer will only see objects within the versioned schema that correspond to the version of the app they have installed in their account.”
      ↩︎ Versioned schemas versus regular schemas
      “Versioned schemas cannot be used as either the source or destination of a clone operation.”
      ↩︎ Versioned schemas versus regular schemas
      “You should always include the CREATE OR ALTER version of this command to ensure that versioned schemas are compatible across versions and patches.”
      ↩︎ Managing schema changes across upgrades
      “modify the existing table by adding the column (in the case of an upgrade)”
      ↩︎ Managing schema changes across upgrades
      “Stateful objects should be created using a regular schema.”
      ↩︎ Exam trap 2
      “Snowpark Container Services is not supported in versioned schemas.”
      ↩︎ Exam trap 3
      “The previous version state changes to FINALIZING until all jobs from version v1 have completed.”
      ↩︎ Prediction
      “To use application roles, tasks, tags, masking policies and Snowpark Container Services within the setup script of an app”
      ↩︎ Checkpoint
    5. 5.
      “Database objects created by the setup script are internal to the app.”
      ↩︎ The setup script: SQL only, internal by default
      “To run additional setup scripts from the main setup script, use the EXECUTE IMMEDIATE FROM command.”
      ↩︎ The setup script: SQL only, internal by default
      “The setup script can be run multiple times during installation and upgrade.”
      ↩︎ The setup script: SQL only, internal by default
      “which implicitly removes privileges that had been previously granted to that procedure”
      ↩︎ The setup script: SQL only, internal by default
      “The setup script only supports using SQL commands. Other languages are not supported.”
      ↩︎ Exam trap 1
      “by default, these objects are invisible and inaccessible to the consumer account directly.”
      ↩︎ Checkpoint
    6. 6.
      “by default, the object is private to the application package and not visible when the app is installed.”
      ↩︎ Bundling data in the package and sharing it with the app
      “When adding a shared object to an application package, you must also share the schema that contains the object.”
      ↩︎ Bundling data in the package and sharing it with the app
      “You cannot share objects outside the application package directly with app installed in the consumer account.”
      ↩︎ Bundling data in the package and sharing it with the app
      “ensures that each version of the Snowflake Native App contains only the definition of the view for that version”
      ↩︎ Bundling data in the package and sharing it with the app
      “You cannot share objects outside the application package directly with app installed in the consumer account.”
      ↩︎ Exam trap 4
    7. 7.
      “Declaring shared content in the manifest is the recommended way to share content.”
      ↩︎ Bundling data in the package and sharing it with the app

    Continue to page 2 of 2

    Native App Logic, Containers, Data Sharing and Distribution

    Spotted a mistake, or was something unclear? Tell us.